Go 18.0 专业五


04. 表达式

<h1>1. 表达式</h1> <p>Golang 表达式 :根据调用者不同,方法分为两种表现形式:</p> <pre><code> instance.method(args...) ---&gt; &lt;type&gt;.func(instance, args...)</code></pre> <p>前者称为 method value,后者 method expression。</p> <p>两者都可像普通函数那样赋值和传参,区别在于 method value 绑定实例,而 method expression 则须显式传参。</p> <pre><code>package main import "fmt" type User struct { id int name string } func (self *User) Test() { fmt.Printf("%p, %v\n", self, self) } func main() { u := User{1, "Tom"} u.Test() mValue := u.Test mValue() // 隐式传递 receiver mExpression := (*User).Test mExpression(&amp;u) // 显式传递 receiver }</code></pre> <p>输出结果:</p> <pre><code> 0xc42000a060, &amp;{1 Tom} 0xc42000a060, &amp;{1 Tom} 0xc42000a060, &amp;{1 Tom}</code></pre> <p>需要注意,method value 会复制 receiver。</p> <pre><code>package main import "fmt" type User struct { id int name string } func (self User) Test() { fmt.Println(self) } func main() { u := User{1, "Tom"} mValue := u.Test // 立即复制 receiver,因为不是指针类型,不受后续修改影响。 u.id, u.name = 2, "Jack" u.Test() mValue() }</code></pre> <p>输出结果</p> <pre><code> {2 Jack} {1 Tom}</code></pre> <p>在汇编层面,method value 和闭包的实现方式相同,实际返回 FuncVal 类型对象。</p> <pre><code> FuncVal { method_address, receiver_copy }</code></pre> <p>可依据方法集转换 method expression,注意 receiver 类型的差异。</p> <pre><code>package main import "fmt" type User struct { id int name string } func (self *User) TestPointer() { fmt.Printf("TestPointer: %p, %v\n", self, self) } func (self User) TestValue() { fmt.Printf("TestValue: %p, %v\n", &amp;self, self) } func main() { u := User{1, "Tom"} fmt.Printf("User: %p, %v\n", &amp;u, u) mv := User.TestValue mv(u) mp := (*User).TestPointer mp(&amp;u) mp2 := (*User).TestValue // *User 方法集包含 TestValue。签名变为 func TestValue(self *User)。实际依然是 receiver value copy。 mp2(&amp;u) }</code></pre> <p>输出:</p> <pre><code> User: 0xc42000a060, {1 Tom} TestValue: 0xc42000a0a0, {1 Tom} TestPointer: 0xc42000a060, &amp;{1 Tom} TestValue: 0xc42000a100, {1 Tom}</code></pre> <p>将方法 &quot;还原&quot; 成函数,就容易理解下面的代码了。</p> <pre><code>package main type Data struct{} func (Data) TestValue() {} func (*Data) TestPointer() {} func main() { var p *Data = nil p.TestPointer() (*Data)(nil).TestPointer() // method value (*Data).TestPointer(nil) // method expression // p.TestValue() // invalid memory address or nil pointer dereference // (Data)(nil).TestValue() // cannot convert nil to type Data // Data.TestValue(nil) // cannot use nil as type Data in function argument }</code></pre>

页面列表

ITEM_HTML