一个&引发的血案

450 阅读1分钟

遥想写js时,写方法跟写属性一样so easy。但是在学go的时候,妈妈有点担心了。

    // goinaction中的一个例子    
    func main() {
        var b bytes.Buffer
        b.Write([]byte("hello"))
	fmt.Fprintf(&b, "world")
	io.Copy(os.Stdout, &b)
    }

因为不熟,在敲这段代码的时候,我把fmt.Fprintf(&b, "world")敲成了fmt.Fprintf(b, "world"),然后竟然报错了。

然后我就万脸茫然?

记得学struct的时候,可以这样实现方法的:

    type Person struct {
         name string
    }
    
    func (p *Person) sayHi() {
	fmt.Println(p.name + " hello world")
    }
    
    func main() {
        p := Person{"zhazha"}
        p.sayHi() // zhazha hello world
        // 或者
        (&p).sayHi()
    }    

为什么fmt.Fprintf(&b, "world")只能传入&b呢?

竟然这一节讲interface,那肯定跟interface有关系?写个小demo测试一下

    // 随便定义了一个interface
    type Hier interface {
	sayHi()
    }

    type Person struct {
         name string
    }
    // 实现了Hier的接口
    func (p *Person) sayHi() {
	fmt.Println(p.name + " hello world")
    }
    // 这里的方法传入的是一个实现Hier接口的值
    func someFuncTakePPoint(h Hier) {
        h.sayHi()
    }
    
    func main() {
        p := Person{"zhazha"}
        // 果然        
        someFuncTakePPoint(&p)
        // 这里如果用p作参数,会编译出错
        // cannot use p (variable of type Person) as Hier value in argument to someFuncTakePPoint
        // someFuncTakePPoint(p)
    }

Recap

  • 如果方法的接受者是struct的指针类型,可以用值或者值的指针调用该方法。可实现的原因是编译器会帮忙处理。
  • 如果结构体实现了interface,即实现了interface定义的方法,且这个方法的接收者是指针类型时,在使用这个结构体作为接口类型的参数时,只能用值的指针。