Pit and analysis of the type conversion of Golang

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

First, let's look at an example

type Stringer interface {    String() string}type String struct {    data string}func (s *String) String() string {    return data}

Above is the type, and then

func GetString() *String {    return nil}func CheckString(s Stringer) bool {    return s == nil}func main() {    println(CheckString(GetString()))}

What do you think the answer is?
Of course, such a strange way of questioning the answer is unreasonable false.
In the CheckString inside, S is not equal to nil.
If you think it's incredible, you can keep looking.

It should be emphasized that this article only applies to Golang.

Type conversions

The official documentation clearly states how the type T can be converted to V, and normally, T must be explicitly declared to be converted to V.

func check64(v int64){}func check(v int){}a := 5b := int64(10)check64(int64(a))check(int(b))check64(a) // panic

However, if the assignability is satisfied, the type conversion can be performed automatically without an explicit declaration
Among them, the more easily overlooked is the two:

    1. X is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type.
    2. X is an untyped constant representable by a value of type T.
const a = 5func check64(v int64){}func checkSlice(v []int){}check64(a) // -> check64(int64(a))check64(1024) // -> check64(int64(1024))checkSlice(nil) // -> checkSlice([]int(nil))

The above code is able to execute correctly, it should be noted that 1024 is also a constant (here is a description of Integer literals a integer constant ).

Analysis

When you know it, look at the example I just started.

func GetString() *String {    return nil}println(interface{}(GetString()))

What is thrown out here is actually *String(nil) , if print comes out, it should be a value of (0x****, 0x0)

What is required PS is that when print prints a interface, the first value is a pointer to a variable's dynamic type, and the second value is a pointer to the actual value. Here in order to get the dynamic type, deliberately converted to interface{}

Then, to CheckString ,

func CheckString(s Stringer) bool {    return s == nil}

This nil will be converted Stringer(nil) , printed with print Dafa, and the result is(0x0, 0x0)

Is it strange that print prints out the first is a type of pointer, why is it 0? First, a variable has a dynamic type and a static type, and if it is not interface, the static type is the same as the dynamic type, and when interface, the static type is the value of interface, and the dynamic type is the actual type of the value that he stores. Print is a dynamic type, because here he has a value of 0, and the dynamic type is certainly 0.

When executing at CheckString(GetString()) this time, S *String(nil) is, and nil is <nil>(nil) (null type of NULL pointer), when the equals judgment, according to spec, interface will be the dynamic type same as dynamic value the exact time to return true. So this is obviously false.

How to not step on the pit

Although the example seems to be unreasonable, but in fact it is easier to step on the pit, especially when you want to die ...

type SpecError struct {    err Error}func NewSpecError(err error) *SpecError {    if err == nil {        return nil    }    return &SpecError{err}}func (se *SpecError) Error() string {    return se.err.Error()}func GetObjByID(id string) (*Obj, error) {    obj, err := xxxxx(id)    return obj, NewSpecError(err)}func main(){    obj, err := GetObjByID("123")    if err != nil {        panic(err)    }    。。。}

Well, I admit that if you don't die, you're not going GetObjByID to get it. if err != nil

Thinking

type RouterString func() stringtype RouterBytes func() []bytefunc AddRouter(router interface{}) {    switch router := router.(type) {    case RouterString:        println("string")    case RouterBytes:        println("bytes")    default:        println("unknown types")    }}func main() {    AddRouter(func() string{        println("hello?")    })}

What's wrong with this piece of code? How to change?

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.