2017-02-15 77 views
0
type MyError struct { 
    errors []string 
} 

func (t *MyError) Error() string { 
    if t == nil { 
     fmt.Println("t ptr empty") 
     return "" 
    } 
    pointers := make([]string, 0, len(t.errors)) 
    for i, r := range t.errors { 
     pointers[i] = r 
    } 
    sort.Strings(pointers) 
    return fmt.Sprintf("n error(s) decoding:\n\n%s", len(t.errors), strings.Join(pointers, ",")) 
} 

func main() { 
    var err *MyError 
    err.Error() // expected "panic: runtime error: invalid memory address or nil pointer dereference" here 
} 

變量err爲零,所以調用err.Error()方法應該會導致恐慌「運行時錯誤:無效的內存地址或零指針取消引用」,但方法調用成功。爲什麼不這麼恐慌?在零結構指針上調用方法不會驚慌。爲什麼不?

+0

因爲語言規範是這樣說的嗎? – Volker

回答

1

請閱讀:https://golang.org/ref/spec#The_zero_value

When storage is allocated for a variable, either through a declaration or a call of new, or when a new value is created, either through a composite literal or a call of make, and no explicit initialization is provided, the variable or value is given a default value. Each element of such a variable or value is set to the zero value for its type: false for booleans, 0 for integers, 0.0 for floats, "" for strings, and nil for pointers, functions, interfaces, slices, channels, and maps. This initialization is done recursively, so for instance each element of an array of structs will have its fields zeroed if no value is specified.

因此,在你的代碼,var err *MyErrornil,你可以叫err.Error()是好的甚至err = nill

**

In Go, the function to be called by the Expression.Name() syntax is entirely determined by the type of Expression and not by the particular run-time value of that expression, including nil.

**

+0

非常感謝。 – cdh0805010118

2

Michael Jones explained this well(作爲回答複製):

In Go the function to be called by the Expression.Name() syntax is entirely determined by the type of Expression and not by the particular run-time value of that expression, including nil.

In this manner, the invocation of a method on a nil pointer of a specific type has a clear and logical meaning.

Those familiar with vtable[] implementations will find this odd at first, yet, when thinking of methods this way, it is even simpler and makes sense. Think of:

func (p *Sometype) Somemethod (firstArg int) {} 

as having the literal meaning:

func SometypeSomemethod(p *Sometype, firstArg int) {} 

and in this view, the body of SometypeSomemethod() is certainly free to test it's (actual) first argument (p *Sometype) for a value of nil.

相關問題