首页>>后端>>Golang->浅析Effective Go Method

浅析Effective Go Method

时间:2023-11-30 本站 点击:0

Pointers vs. Values

正如ByteSize那样,我们可以为任何已命名的类型(除了指针或接口)定义方法; 接收者可不必为结构体。

在之前讨论切片时,我们编写了一个Append函数。 我们也可将其定义为切片的方法。为此,我们首先要声明一个已命名的类型来绑定该方法, 然后使该方法的接收者成为该类型的值。

typeByteSlice[]bytefunc(sliceByteSlice)Append(data[]byte)[]byte{//BodyexactlythesameastheAppendfunctiondefinedabove.}

我们可以通过指针的方式作为ByteSlice的接收者。这样就可以重写

func(p*ByteSlice)Append(data[]byte){slice:=*p//Bodyasabove,withoutthereturn.*p=slice}

示例

typeByteSlice[]bytefunc(sliceByteSlice)Append(data[]byte)[]byte{//BodyexactlythesameastheAppendfunctiondefinedabove.byteSlice:=append(slice,data...)returnbyteSlice}func(p*ByteSlice)Append2(data[]byte){byteSlice:=append(*p,data...)*p=byteSlice}funcmain(){slice:=ByteSlice{}byteSlice:=append(slice,byte(1))bytes:=byteSlice.Append([]byte{byte(2)})fmt.Println(bytes)//[12]byteSlice.Append2([]byte{byte(3)})fmt.Println(byteSlice)//[31]}

事实上我们可以做到更好。如我们修改方法跟write接口一样。

func(p*ByteSlice)Write(data[]byte)(nint,errerror){slice:=*p//Againasabove.*p=slicereturnlen(data),nil}

//WriteristheinterfacethatwrapsthebasicWritemethod.////Writewriteslen(p)bytesfromptotheunderlyingdatastream.//Itreturnsthenumberofbyteswrittenfromp(0<=n<=len(p))//andanyerrorencounteredthatcausedthewritetostopearly.//Writemustreturnanon-nilerrorifitreturnsn<len(p).//Writemustnotmodifytheslicedata,eventemporarily.////Implementationsmustnotretainp.typeWriterinterface{Write(p[]byte)(nint,errerror)}

那么类型*ByteSlice就满足了标准的io.Writer接口,这将非常实用。 例如,我们可以通过打印将内容写入。

varbByteSlicefmt.Fprintf(&b,"Thishourhas%ddays\n",7)

我们将ByteSlice的地址传入,因为只有*ByteSlice才满足io.Writer。以指针或值为接收者的区别在于:值方法可通过指针和值调用, 而指针方法只能通过指针来调用。

之所以会有这条规则是因为指针方法可以修改接收者;通过值调用它们会导致方法接收到该值的副本, 因此任何修改都将被丢弃,因此该语言不允许这种错误。

不过有个方便的例外:若该值是可寻址的, 那么该语言就会自动插入取址操作符来对付一般的通过值调用的指针方法。在我们的例子中,变量b是可寻址的,因此我们只需通过b.Write来调用它的Write方法,编译器会将它重写为(&b).Write。

顺便一提,在字节切片上使用Write的想法已被bytes.Buffer所实现。

//Writeappendsthecontentsofptothebuffer,growingthebufferas//needed.Thereturnvaluenisthelengthofp;errisalwaysnil.Ifthe//bufferbecomestoolarge,WritewillpanicwithErrTooLarge.func(b*Buffer)Write(p[]byte)(nint,errerror){b.lastRead=opInvalidm,ok:=b.tryGrowByReslice(len(p))if!ok{m=b.grow(len(p))}returncopy(b.buf[m:],p),nil}

引用

Effective Go - The Go Programming Language (google.cn)

方法 |《高效的 Go 编程 Effective Go 2020》| Go 技术论坛 (learnku.com)


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/Golang/4525.html