返回Go泛型类型

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

Returning Go Generic Type

问题

以下代码在第res = fmt.Sprintf("%s + %s", i, j)行无法编译通过,报错信息为:cannot use fmt.Sprintf("%s + %s", i, j) (value of type string) as type T in assignment

如果我只是简单地return i + j,它确实允许我返回一个int,并且代码可以编译和运行。

我缺少一些基本的理解,需要指点正确的方向。

package main

import (
	"fmt"
	"reflect"
)

type Adder interface {
	string | int
}

func Add[T Adder](i, j T) T {
	var res T

	switch reflect.TypeOf(i).Name() {
	case "int":
		res = i + j
	case "string":
		res = fmt.Sprintf("%s + %s", i, j)
	}

	return res
}

func main() {
	it := Add(3, 4)
	st := Add("one", "two")

	fmt.Println("Int:", it)
	fmt.Println("Str:", st)
}
英文:

The following fails to compile on line res = fmt.Sprintf("%s + %s", i, j) with the error: cannot use fmt.Sprintf("%s + %s", i, j) (value of type string) as type T in assignment

It does allow me to return an int and the code does compile and run if I simply return i + j.

I'm missing some fundamental understanding and need to be pointed in the correct direction.


import (
	"fmt"
	"reflect"
)

type Adder interface {
	string | int
}

func Add[T Adder](i, j T) T {
	var res T

	switch reflect.TypeOf(i).Name() {
	case "int":
		res = i + j
	case "string":
		res = fmt.Sprintf("%s + %s", i, j)
	}

	return res
}
func main() {
	it := Add(3, 4)
	st := Add("one", "two")

	fmt.Println("Int:", it)
	fmt.Println("Str:", st)
}

答案1

得分: 2

看一下Add函数对字符串的操作:

func Add[string](i, j string) string {
    var res string

    switch reflect.TypeOf(i).Name() {
    case "int":
        res = i + j
    case "string":
        res = fmt.Sprintf("%s + %s", i, j)
    }

    return res
}

这是可以的。表达式i + j只是将两个字符串连接起来。再看一下Add函数对整数的操作:

func Add[int](i, j int) int {
    var res int

    switch reflect.TypeOf(i).Name() {
    case "int":
        res = i + j
    case "string":
        res = fmt.Sprintf("%s + %s", i, j)
    }

    return res
}

这是一个类型错误。并不重要"string"分支在运行时永远不会被执行-整个函数必须进行类型检查!

(请注意,Go语言实际上不通过插入类型来实例化泛型-但你可以理解这个概念。)

英文:

Take a look at what Add does for strings:

func Add[string](i, j string) string {
    var res string

    switch reflect.TypeOf(i).Name() {
    case "int":
        res = i + j
    case "string":
        res = fmt.Sprintf("%s + %s", i, j)
    }

    return res
}

This is ok. The expression i + j just concatenates two strings. Take a look at what Add does for int:

func Add[int](i, j int) int {
    var res int

    switch reflect.TypeOf(i).Name() {
    case "int":
        res = i + j
    case "string":
        res = fmt.Sprintf("%s + %s", i, j)
    }

    return res
}

This is a type error. It does not matter that the "string" branch is never taken at runtime—the entire function must typecheck!

(Note that Go does not actually instantiate generics by inserting the types—but you get the idea.)

答案2

得分: 1

通用函数的主体必须对所有可能的类型都有效。如果res是int,那么"string"情况无法编译。如果res是string,那么两种情况都是有效的表达式。

您可以通过声明以下内容来尝试这个想法:

type Adder interface {
    string 
}

并进行必要的更改。您仍然需要:

res = T(fmt.Sprintf("%s + %s", i, j))
英文:

The body of the generic function must be valid for all possible types. If res is int, the "string" case cannot be compiled. If res is string, both cases are valid expressions.

You can try this idea by declaring

type Adder interface {
    string 
}

and making the necessary changes. You still need to:

        res = T(fmt.Sprintf("%s + %s", i, j))

huangapple
  • 本文由 发表于 2022年5月5日 03:01:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/72118187.html
匿名

发表评论

匿名网友

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

确定