Go语言中的类型切换(type-switch)如何处理指向nil的指针?

huangapple go评论78阅读模式
英文:

go type-switch how to deal with point to nil

问题

像这样,如果msg指向null值,如何在clean code中处理它?

func test(a SomeType) {
    switch msg := a.(type) {
    case *type1:
        dosomething1(a)
    case *type2:
        dosomething2(a)
    case *type3:
        dosomething3(a)
    default:
        do()
    }
}

主函数可能是这样的:

func main() {
    var b_ptr *stTest
    aa := interface{}(b)
    test(aa)
}

type test struct {
    c int
    d string
}

b_ptr是一个指针,但它指向nil,我想在test函数中判断它。如果我在test函数中使用b_ptr,例如打印a.ca.d,程序会崩溃。

我通过以下方式解决了这个问题。在每个case中使用if语句,检查msg是否为nil,但这样做太愚蠢了。

func test(a SomeType) {
    switch msg := a.(type) {
    case *type1:
        if msg == nil {
            return
        }
        dosomething1(a)
    case *type2:
        if msg == nil {
            return
        }
        dosomething2(a)
    case *type3:
        if msg == nil {
            return
        }
        dosomething3(a)
    default:
        do()
    }
}
英文:

like this, if msg point to null value, how to deal with it in clean code

func test(a SomeType) {
    switch msg := a.(type) {
    case *type1:
        dosomething1(a)
    case *type2:
        dosomething2(a)
    case *type3:
        dosomething3(a)
    default:
        do()
}

the main func may be this

func main() {
    var b_ptr *stTest
    aa := interface{}(b)
    test(aa)
}

type test struct {
	c int
	d string
}

b_ptr is a pointer, but it point to nil, i want to judge it in test func
if i use b_ptr in test func, eg: print a.c or a.d, it will crash.

i do it by this way. do if(), everywhere use a, but it too stupid.

func test(a SomeType) {
    switch msg := a.(type) {
    case *type1:
        if msg == nil {
            return
        }
        dosomething1(a)
    case *type2:
        if msg == nil {
            return
        }
        dosomething2(a)
    case *type3:
        if msg == nil {
            return
        }
        dosomething3(a)
    default:
        do()
}

答案1

得分: 1

通常情况下,这应该被视为调用者的问题,因此处理后果应该是调用者的责任。传递非nil值的接口是一种不好的做法,除非这是有意为之的。

然而,如果你无法避免使用非nil指针的接口,你可以使用reflect来检查底层值是否为nil

func test(a SomeType) {
	if rv := reflect.ValueOf(a); !rv.IsValid() || rv.IsNil() {
		return
	}
	switch msg := a.(type) {
	case *type1:
		dosomething1(a)
	case *type2:
		dosomething2(a)
	case *type3:
		dosomething3(a)
	default:
		do()
	}
}
英文:

Generally this ought to be considered a problem with the caller, and therefore it should be the caller's job to deal with the fallout. Passing around non-nil interfaces that hold nil values is bad practice unless it's intentional/expected.

If you can't avoid the non-nil interface with nil-pointer however, then you can use reflect to check if the underlying value is nil.

func test(a SomeType) {
	if rv := reflect.ValueOf(a); !rv.IsValid() || rv.IsNil() {
		return
	}
	switch msg := a.(type) {
	case *type1:
		dosomething1(a)
	case *type2:
		dosomething2(a)
	case *type3:
		dosomething3(a)
	default:
		do()
	}
}

huangapple
  • 本文由 发表于 2021年9月13日 19:48:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/69162113.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定