接口包含类型约束:无法在转换中使用接口。

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

interface contains type constraints: cannot use interface in conversion

问题

type Number interface {
	int | int64 | float64
}

type NNumber interface {
}

// 接口包含类型约束
// type NumberSlice []Number

type NNumberSlice []NNumber

func main() {
	var b interface{}
	b = interface{}(1)
	fmt.Println(b)

	// 接口包含类型约束
    // 无法像这样初始化接口 Number 的切片(包含特定类型约束或可比较)
	//a := []Number{Number(1), Number(2), Number(3), Number(4)}
	//fmt.Println(a)

	aa := []interface{}{interface{}(1), interface{}(2), interface{}(3), 4}
	fmt.Println(aa)

	aaa := []NNumber{NNumber(1), NNumber(2), NNumber(3), 4}
	fmt.Println(aaa)
}

为什么 Number 切片 a 不能像那样初始化?

NumberSliceNNumberSlice 看起来很相似,但是什么是类型约束,这个语法看起来很奇怪。

英文:
type Number interface {
	int | int64 | float64
}

type NNumber interface {
}

//interface contains type constraints
//type NumberSlice []Number

type NNumberSlice []NNumber

func main() {
	var b interface{}
	b = interface{}(1)
	fmt.Println(b)

	// interface contains type constraints
    // cannot use interface Number in conversion (contains specific type constraints or is comparable)
	//a := []Number{Number(1), Number(2), Number(3), Number(4)}
	//fmt.Println(a)

	aa := []interface{}{interface{}(1), interface{}(2), interface{}(3), 4}
	fmt.Println(aa)

	aaa := []NNumber{NNumber(1), NNumber(2), NNumber(3), 4}
	fmt.Println(aaa)
}

why the Number slice a couldn't be initialized like that?

NumberSlice and NNumberSlice look like similarly, but what mean type constraints, it looks strange grammar

答案1

得分: 22

语言规范明确禁止将具有类型元素的接口用作除类型参数约束之外的任何其他用途(引用在接口类型段落下):

基本接口只能用作类型约束,或作为其他用作约束的接口的元素。它们不能是值或变量的类型,也不能是其他非接口类型的组成部分。

嵌入comparable或其他非基本接口的接口也是非基本接口。你的Number接口包含一个联合,因此它也是非基本接口。

以下是一些示例:

// 基本接口:只有方法
type A1 interface {
    GetName() string
}

// 基本接口:只有方法和/或嵌入基本接口
type B1 interface {
    A1
    SetValue(v int)
}

// 非基本接口:嵌入comparable
type Message interface {
    comparable
    Content() string
}

// 非基本接口:具有类型元素(联合)
type Number interface {
    int | int64 | float64
}

// 非基本接口:嵌入非基本接口
type SpecialNumber interface {
    Number
    IsSpecial() bool
}

在变量a的初始化中,你试图使用Number进行类型转换Number(1),这是不允许的。

你只能将Number用作类型参数约束,即限制用于实例化泛型类型或函数的类型。例如:

type Coordinates[T Number] struct {
    x, y T
}

func sum[T Number](a, b T) T {
    return a + b
}
英文:

The language specifications explicitly disallow using interfaces with type elements as anything other than type parameter constraints (the quote is under the paragraph Interface types):

> Interfaces that are not basic may only be used as type constraints, or as elements of other interfaces used as constraints. They cannot be the types of values or variables, or components of other, non-interface types.

An interface that embeds comparable or another non-basic interface is also non-basic. Your Number interface contains a union, hence it is non-basic too.

A few examples:

// basic: only methods
type A1 interface {
    GetName() string
}

// basic: only methods and/or embeds basic interface
type B1 interface {
    A1
    SetValue(v int)
}

// non-basic: embeds comparable
type Message interface {
    comparable
    Content() string
}

// non-basic: has a type element (union)
type Number interface {
    int | int64 | float64
}

// non-basic: embeds a non-basic interface
type SpecialNumber interface {
    Number
    IsSpecial() bool
}

In the initialization of the variable a, you are attempting to use Number in a type conversion Number(1), and this is not allowed.

You can only use Number as a type parameter constraint, i.e. to restrict the types allowed for instantiation of a generic type or function. For example:

type Coordinates[T Number] struct {
    x, y T
}

func sum[T Number](a, b T) T {
    return a + b
}

huangapple
  • 本文由 发表于 2022年2月11日 07:06:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/71073365.html
匿名

发表评论

匿名网友

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

确定