Hãy cẩn thận với interface trong golang
golang
38
Go
39
White

Hoàng Minh Trung viết ngày 18/01/2017

package main

import "fmt"

type StringProvider interface {
    Provide() string
}

type hardcodedStringProvider struct {
    Value string
}

func (p *hardcodedStringProvider) Provide() string {
    return p.Value
}

func NewStringProvider(content string) StringProvider {
    var provider *hardcodedStringProvider = nil
    if content != "" {
        provider = &hardcodedStringProvider{
            Value: content,
        }
    }
    return provider
}

func main() {
    arg := "" // Change this to 'Hello'
    provider := NewStringProvider(arg)
    fmt.Println(provider)
    if provider != nil {
        fmt.Printf("Content: %s\n", provider.Provide())
    } else {
        fmt.Println("No string provider!")
    }
}

Thử chạy đoạn code trên thì bạn sẽ thu được kết quả là:

<nil>
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0xffffffff addr=0x0 pc=0x20030]

goroutine 1 [running]:
panic(0x102440, 0x1040a038)
    /usr/local/go/src/runtime/panic.go:500 +0x720
main.(*hardcodedStringProvider).Provide(0x0, 0x1, 0x1, 0x0)
    /tmp/sandbox227373671/main.go:14 +0x30
main.main()
    /tmp/sandbox227373671/main.go:32 +0x180

Trong đầu bạn sẽ nghĩ là WTF khi mà kết quả print ra là <nil>, mà golang lại thất bại trong việc so sánh if provider != nil {
Điểm bậy bạ ở đây chính là việc bạn gán var provider *hardcodedStringProvider = nil trong khi kết quả trả về của hàm lại là StringProvider.
Do đó golang sẽ làm thêm 1 việc ngoài ý muốn là type convert từ nil thành interface StringProvider.

Trong thực tế thì interface của golang là một struct na ná như dưới đây

type interface struct {
    type *Type
    value *Value
}

Do đó với trường hợp ở trên thì do type khác nhau nên field Type sẽ có giá trị, dẫn đến giá trị trả về là nil, nhưng lại không thật sự là nil :omg:

Tham khảo
https://medium.com/@momchil.dev/beware-of-gos-interfaces-c6c1f3d9f683#.d5hg1su72

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Hoàng Minh Trung

23 bài viết.
65 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
22 1
Bài viết dịch từ http://arslan.io/tenusefultechniquesingo Sử dụng một GOPATH duy nhất Sử dụng đồng thời nhiều GOPATH sẽ không giúp cho hệ thống ...
Hoàng Minh Trung viết hơn 2 năm trước
22 1
White
19 15
(Ảnh) Mục đích của bài viết là hướng dẫn cơ bản nhất cho những ai chưa biết về docker, môi trường thực hiện là mac OS. Chuẩn bị Cài đặt virtua...
Hoàng Minh Trung viết 3 năm trước
19 15
White
17 0
Bài viết dịch từ https://github.com/luciotato/golangnotes/blob/master/OOP.md Mục đích bài viết Học golang dễ dàng hơn với những kiến thức bạn đ...
Hoàng Minh Trung viết hơn 2 năm trước
17 0
Bài viết liên quan
White
10 2
Makefile thực hiện một số thao tác thường dùng trong Go Khi làm project Go mình thường tạo một file Makefile dạng này: Lưu ý nhớ thay thành tên m...
Huy Trần viết hơn 2 năm trước
10 2
White
46 16
Go là gì? Dùng nó cho việc gì? Chắc hẳn đến thời điểm hiện tại, không ai là chưa nghe đến Go (hay còn gọi là Golang), một ngôn ngữ lập trình được ...
Huy Trần viết hơn 3 năm trước
46 16
White
27 3
Introduction Buffering (buffered IO) là một trong những kỹ thuật kinh điển khi chúng ta cần đọc/ghi dữ liệu. Trong bài viết này mình sẽ đi sâu hơn...
Linh Tran Tuan viết 1 năm trước
27 3
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
23 bài viết.
65 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!