实例化接口

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

Instantiating Interfaces

问题

我是你的中文翻译助手,以下是翻译好的内容:

我是Go的新手。有一件事我不明白,为什么当我想单独实例化接口时会出现编译错误,但是当我使用该接口的数组形式时,就没有编译错误。

这个复合字面量会分配一个具有给定值的新结构体实例。

英文:

I am newbie in Go. One thing I don't understand is why I get compile error when I want to instantiate interfaces alone but when I use array form of that interface, then no compiler error.

type Flag interface {
  fmt.Stringer
}

func TestCheckRequiredFlag(t *testing.T) {
	testdata := []struct {
		st []Flag
	}{
		{
			st: []Flag{//allowed
				&StringFlag{Name: ""},
			},
		},
	}

	st := struct {
		st Flag
	}{
		st: Flag{// is not allowed
			&StringFlag{Name: ""},
		},
	}
}

This composite literal allocates a new struct instance with the given values.

答案1

得分: 0

一个接口是一个无法实例化的抽象类型。我们只能创建一个实现该接口的具体类型,然后创建该具体类型的实例。但是当你使用Flag接口的数组形式时,实际上你创建的是一个实现Flag接口的具体类型的切片,这是可以接受的。

英文:

An interface is an abstract type that cannot be instantiated. We can only create a concrete type that implements the interface and then create an instance of that concrete type. But when you use the array form of the Flag interface, you are actually creating a slice of concrete types that implement the Flag interface, which is acceptable.

答案2

得分: 0

大括号 {} 用于表示切片、结构体、数组和映射的字面值。它们不用于接口值。如果你想要一个接口类型的字面值,你必须使用 () 语法,这将调用一个"类型转换"。

例如:

x := MyInterface(&MyStruct{})

x 的类型将是 MyInterface

要更正你的代码:

    st := struct {
        st Flag
    }{
        st: Flag(
            &StringFlag{Name: ""},
        ),
    }

你也可以完全省略类型转换,因为 Go 允许直接将值赋给接口类型的变量,转换是隐式进行的。更明确地说,"可赋值性"规则如下(为了清晰起见进行了编辑):

如果变量 x 的类型是 V,且 T 是一个接口类型,并且 x 实现了 T,那么 x 的值可以赋给类型为 T 的变量。

因此,下面的代码也是可以工作的:

	st := struct {
		st Flag
	}{
		st: &StringFlag{Name: ""},
	}

请注意,在切片、结构体和映射等复合字面值中,给定的值被视为被分配给它们各自的索引、字段或键,就像它们是变量一样,因此可赋值性规则适用。

英文:

Braces {} are used for literal values of slices, structs, arrays and maps. They are not used for interface values. If you want a literal value of an interface type, you have to use the () syntax, which invokes a "type conversion".

For example:

x := MyInterface(&MyStruct{})

x will be of type MyInterface.

To correct your code:

    st := struct {
        st Flag
    }{
        st: Flag(
            &StringFlag{Name: ""},
        ),
    }

You can also remove the type conversion altogether, as Go allows direct assignment to interface values, with the conversion being implicit. More explicitly, the assignability rule says (edited for clarity):

> A value x of type V is assignable to a variable of type T if T is an interface type and x implements T.

So, this code will also work:

	st := struct {
		st Flag
	}{
		st: &StringFlag{Name: ""},
	}

Note that in composite literals such as slices, structs and maps, the values given are considered to be assigned to their respective index, field or key, as if they were variables, so the assignability rules apply.

huangapple
  • 本文由 发表于 2023年4月2日 00:49:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/75907573.html
匿名

发表评论

匿名网友

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

确定