Golang编译错误求助:如何解决常见的编译问题
Golang编译错误求助:如何解决常见的编译问题 我对Golang还比较陌生。我正在尝试实现类似于C语言中的带标签联合(tagged union)的功能。我在Go and Algebraic Data Types - Eli Bendersky’s website上找到了一些示例代码。
我认为我理解了这个示例,并尝试在我的代码中模仿它。以下是我的完整程序中引发了一个我不理解的错误的部分代码片段。在我看来,一切似乎都没问题。
package main
type Obj interface {
isObj()
}
type Tspecial struct {
subtype int
}
func (Tspecial) isObj() {}
func make_special(subtype int) *Obj {
n := Tspecial{subtype}
return &n
}
func main() {
// dot := make_special(1)
}
使用Go版本1.19.1时,出现了以下错误:
./test.go:15:9: 无法将 &n (类型为 *Tspecial 的值) 用作返回语句中的 *Obj 类型: *Tspecial 未实现 *Obj (类型 *Obj 是指向接口的指针,而不是接口)
我认为我已经让 Tspecial 实现了 Obj,那么为什么 Tspecial 的地址不能是 *Obj 呢?
无论如何,能否有人告诉我我的错误在哪里。我相信一定有办法实现我想要的功能。
更多关于Golang编译错误求助:如何解决常见的编译问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
嗯,你的建议编译通过了,但我无法理解为什么会这样。这在我看来非常不对劲,因为函数 make_special 声明它返回一个 Obj,而不是一个指向 Obj 的指针,而你的代码返回的是 &n,即 n 的地址,这应该是一个指向 Obj 的指针。
有人能慢慢地解释一下,或者给我指出相关文档,帮助我理解这个问题吗?我一定是遗漏了一些根本性的东西。
更多关于Golang编译错误求助:如何解决常见的编译问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
区别在于指向结构的指针和指向接口的指针。 请查看以下代码:
func writeObj(o Obj) {
fmt.Printf("[%T] %+v\n", o, o)
}
func main() {
a := Tspecial{1}
var b *Tspecial = &Tspecial{2}
writeObj(a)
writeObj(b)
}
writeObj 可以通过接口接收一个结构体以及指向该结构体的指针,但不能接收指向接口的指针。

package main
import "fmt"
type Obj interface {
isObj()
}
type Tspecial struct {
subtype int
}
func (ts *Tspecial) isObj() {}
func make_special(subtype int) Obj {
n := Tspecial{subtype}
return &n
}
func main() {
dot := make_special(1)
fmt.Println(dot)
}
当然!
- 接口值严格来说既不是指针,也不是非指针,它只是一个接口。
如何在 Go 中使用接口
在我开始用 Go 编程之前,我主要使用 Python 工作。作为一名 Python 程序员,我发现学习在 Go 中使用接口极其困难。也就是说,基础知识很容易,…
谢谢你,Yamil。我现在知道如何稍微修改我的代码来让它工作了。
但是,有人能向我解释一下为什么Gonzalo的例子能工作吗?就是这个:
package main
import "fmt"
type Obj interface {
isObj()
}
type Tspecial struct {
subtype int
}
func (ts *Tspecial) isObj() {}
func make_special(subtype int) Obj {
n := Tspecial{subtype}
return &n
}
func main() {
dot := make_special(1)
fmt.Println(dot)
}
make_special 函数声明它返回一个 Obj,而不是一个指向 Obj 的指针,然而该函数返回的是 &n,一个指向 Tspecial(它是一个 Obj)的指针。为什么这不是一个错误?然后,回到 main 函数,Println(dot) 显示 dot 是 &{1},这是一个指向 Tspecial 的指针。也就是说,make_special 声明它返回一个 Obj,但它显然返回了一个 *Obj。
请先检查这个版本:
package main
import (
"fmt"
"reflect"
)
type Obj interface {
isObj()
}
type Tspecial struct {
subtype int
}
func (t Tspecial) isObj() {
fmt.Println("Implementation of isObj in Tspecial")
}
func make_special(subtype int) Obj {
n := Tspecial{subtype}
n.isObj()
fmt.Println(reflect.TypeOf(n))
return n
}
func main() {
dot := make_special(1)
fmt.Println(dot)
fmt.Println(reflect.TypeOf(dot))
}
它打印: isObj:Tspecial 实现 TypeOf(n)= main.Tspecial dot= {1} TypeOf(dot)= main.Tspecial
实际上,Tspecial 被视为 Obj,因为它实现了该接口所需的所有功能。 问题在于指针。指向 Tspecial 的指针和指向 Obj 的指针是两回事。
要从 make_special 返回一个 *Obj,你需要创建一个该类型的临时对象,将 “n” 转换为该类型,然后返回其指针。 类似于这样:
func make_special(subtype int) *Obj {
n := Tspecial{subtype}
n.isObj()
fmt.Println(reflect.TypeOf(n))
o := Obj(n)
return &o
}
这是一个常见的Go语言接口使用误区。问题在于你返回的是接口指针 *Obj 而不是接口值 Obj。
在Go中,接口本身已经是一个引用类型,通常不需要使用接口指针。*Obj 表示指向接口的指针,而不是指向实现了该接口的类型的指针。
以下是修正后的代码:
package main
type Obj interface {
isObj()
}
type Tspecial struct {
subtype int
}
func (Tspecial) isObj() {}
// 返回接口值,而不是接口指针
func make_special(subtype int) Obj {
n := Tspecial{subtype}
return n // 直接返回值,不需要取地址
}
func main() {
dot := make_special(1)
_ = dot
}
如果你确实需要返回指针,可以这样修改:
package main
type Obj interface {
isObj()
}
type Tspecial struct {
subtype int
}
func (*Tspecial) isObj() {} // 使用指针接收器
func make_special(subtype int) Obj {
n := &Tspecial{subtype} // 创建指针
return n // 返回接口值,其中包含指针
}
func main() {
dot := make_special(1)
_ = dot
}
关键点:
- 接口在Go中已经是引用类型,通常直接使用
Obj而不是*Obj - 当方法使用指针接收器时,需要传递指针才能满足接口
- 接口值内部可以包含具体类型的指针
你的原始代码尝试返回 *Obj,这实际上创建了一个指向接口的指针,而不是包含具体类型指针的接口值。

