英文:
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'
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论