Go – 如何在方法中修改扩展的原始类型?

huangapple go评论81阅读模式
英文:

Go - How to modify extended-primitive types in its method?

问题

在Go语言中,我们可以扩展原始类型,比如string,并定义它的方法。

func (s MyStr) Saying() MyStr {
    return s + ",有人说。"
}

我该如何定义处理指向自身的指针并修改它的方法?

下面的方法是不起作用的:

func (s *MyStr) Repeat() {
    s = s + ", " + s
}

类型不匹配`*MyStr``string`
英文:

In go, we can extend primitive types such as string or so, and can define its method.

func (s MyStr) Saying() MyStr {
	return s + ", someone said."
}

How can I define methods handling pointer of its self and modify it.

The method below doesn't work:

func (s *MyStr) Repeat() {
	s = s + ", " + s
}

(mismatched types *MyStr and string)

答案1

得分: 0

对这段代码最大的异议应该是字符串是不可变的。因此,按照设计,需要经过多个间接步骤才能使其正常工作。如果MyStr代替为bytes.Buffer或其他可变类型,那么就会更容易实现所需的行为。

然而,在我们讨论这个问题之前,有一个非常简单和明显的错误需要修复。要将s和", "相加,可以将字符串转换为MyStr,像这样:

temp := *s + MyStr(", ") + *s
s = &temp // 仍然无法正常工作

当然,由于字符串是不可变的,你没有改变s原来指向的字符串。你改变的s只是在函数调用内部创建的副本;你实际上没有实现任何目标。

下面是使用bytes.Buffer包的版本,它是可变的:

package main

import "fmt"
import "bytes"

// 不是别名类型,而是嵌入类型,
// 这样我们就可以将其用作接收器
type MyStr struct {
    *bytes.Buffer
}

func (s MyStr) Repeat() {
    temp := s.Bytes()
    s.Write(bytes.NewBufferString(", ").Bytes())
    s.Write(temp)
}

func main() {
    a := MyStr{bytes.NewBufferString("a")}
    a.Repeat()
    fmt.Println(a)
}

// 输出 'a, a'

希望能对你有所帮助!

英文:

The biggest objection one should have to this code is that strings are immutable. So, as designed, it would take many steps of indirection to get this to work. If MyStr was instead a bytes.Buffer, or something mutable, then it would be a lot easier to get the behaviour you desire.

Before we get to that, however, there's a very easy and obvious bug that needs fixing. To add s and ", ", you can convert the string to a MyStr, like so:

temp := *s + MyStr(", ") + *s 
s = &temp //Still doesn't work

Of course, since strings are immutable, you haven't changed the string that the s used to point to. The s you have changed is just a copy that was created inside the function call; you haven't really achieved anything.

Here is a version that uses the bytes.Buffer package, which IS mutable.

package main

import "fmt"
import "bytes"

// Not aliasing the type, but embedding, 
// so that we can use it as a receiver
type MyStr struct {*bytes.Buffer}

func (s MyStr) Repeat() {
    temp := s.Bytes()
    s.Write(bytes.NewBufferString(", ").Bytes())
    s.Write(temp)
}


func main() {
    a := MyStr{bytes.NewBufferString("a")}
    a.Repeat()
    fmt.Println(a)
}

// Prints 'a, a'

huangapple
  • 本文由 发表于 2014年5月26日 20:36:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/23870319.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定