为了账号安全,请及时绑定邮箱和手机立即绑定

如何声明和使用可以存储字符串和 int 值的结构字段?

如何声明和使用可以存储字符串和 int 值的结构字段?

Go
杨魅力 2022-11-08 15:34:08
我有以下结构:type testCase struct {   input   string   isValid bool}我想在多个测试中使用这个结构,输入可以是 astring或 anint等。我可以在处理时将int输入转换为string并将其转换回int,或者我可以定义两个不同的结构,例如testCaseInt,testCaseStruct这将解决我的问题,但怎么做我通过转换input为interface?我是 Go 新手,并尝试用谷歌搜索,但可能找不到,因为我不知道要搜索什么。
查看完整描述

4 回答

?
动漫人物

TA贡献1815条经验 获得超10个赞

如何在 Go 中声明和使用可以同时存储字符串和 int 值的变量?

你不能。Go 的类型系统(从 Go 1.17 开始)不提供 sum 类型。

你将不得不等待 Go 1.18。


查看完整回答
反对 回复 2022-11-08
?
明月笑刀无情

TA贡献1828条经验 获得超4个赞

权衡是在静态类型和灵活容器之间。


在 Go 1.17 之前,您不能拥有具有不同静态类型的结构字段。最好的方法是interface{}, 然后在使用时断言动态类型。这有效地允许您testCases在运行时拥有任一类型的容器。


type testCase struct {

   input   interface{}

   isValid bool

}


func main() {

    // can initialize container with either type

    cases := []testCase{{500, false}, {"foobar", true}}


    // must type-assert when using

    n := cases[0].(int)

    s := cases[1].(string)

}

使用 Go 1.18,您可以稍微提高类型安全性,以换取更少的灵活性。


使用联合对结构进行参数化。这静态地限制了允许的类型,但现在必须显式实例化结构,因此您不能拥有具有不同实例化的容器。这可能与您的目标兼容,也可能不兼容。

type testCase[T int | string] struct {

   input   T

   isValid bool

}


func main() {

    // must instantiate with a concrete type

    cases := []testCase[int]{

        {500, false},     // ok, field takes int value

        /*{"foobar", true}*/, // not ok, "foobar" not assignable to int

    }

    // cases is a slice of testCase with int fields

}

不,实例化testCase[any]是一个红鲱鱼。首先,any只是不满足约束int | string;即使您放松了这一点,它实际上也比 Go 1.17 解决方案更糟糕,因为现在您不能只testCase在函数参数中使用,而是必须使用完全testCase[any].


使用联合参数化结构,但仍使用interface{}/any作为字段类型:(如何)我可以在 go 中实现通用的“Either”类型吗?. 这也不允许同时拥有两种类型的容器。

一般来说,如果您的目标是使用任一类型的灵活容器类型(切片、映射、通道),则必须将字段保持为interface{}/any并断言使用情况。如果您只想在编译时重用具有静态类型的代码并且您使用的是 Go 1.18,请使用联合约束。


查看完整回答
反对 回复 2022-11-08
?
侃侃尔雅

TA贡献1801条经验 获得超15个赞

只有你能做的是,用 interface{} 改变字符串


检查播放(它工作正常)


https://go.dev/play/p/pwSZiZp5oVx


package main


import "fmt"


type testCase struct {

    input   interface{}

    isValid bool

}


func main() {


    test1 := testCase{}

    test1.input = "STRING".  // <-------------------STRING

    fmt.Printf("input: %v \n", test1)


    test2 := testCase{}

    test2.input = 1      // <-------------------INT

    fmt.Printf("input: %v \n", test2)


}


查看完整回答
反对 回复 2022-11-08
?
守候你守候我

TA贡献1802条经验 获得超10个赞

方法一:


package main


import (

    "fmt"

)


func main() {

    var a interface{}

    a = "hi"

    if valString, ok := a.(string); ok {

        fmt.Printf("String: %s", valString)

    }

    a = 1

    if valInt, ok := a.(int); ok {

        fmt.Printf("\nInteger: %d", valInt)

    }

}

方法二:


package main


import (

    "fmt"

)


func main() {

    print("hi")

    print(1)

}


func print(a interface{}) {

    switch t := a.(type) {

    case int:

        fmt.Printf("Integer: %v\n", t)

    case string:

        fmt.Printf("String: %v\n", t)

    }

}


查看完整回答
反对 回复 2022-11-08
  • 4 回答
  • 0 关注
  • 75 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信