Golang有类似于C++的decltype的功能吗?

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

Does Golang have something like C++'s decltype?

问题

C++有decltype(expr)。你可以声明一个与其他表达式类型相同的对象。例如:
decltype('c') a[4]将声明一个包含4个字符的数组。这只是一个简单的例子,但这个特性是有用的。下面是一个用于UDP服务器的Go代码示例:

conn, err := net.ListenUDP("udp", udp_addr)
...
defer conn.Close()
...
_, err = conn.WriteToUDP(data, addr)

重要的是,我知道我可以对函数的结果(在这种情况下是连接,即ListenUDP的结果)做什么,但我不知道这个类型是什么。在这里,由于Go的类型推断,我不需要知道。但是,如果我想创建5个连接,我希望有一个包含5个"ListenUDP的结果"的数组。我无法做到这一点。我尝试过的最接近的方法是:

ret_type := reflect.TypeOf(net.DialUDP)
first_param_type := reflect.TypeOf(ret_type.Out(0))
my_arr := reflect.ArrayOf(4, first_param_type)
my_arr[0] = nil

但是最后一行不起作用。在Go中有没有一种方法可以实现这个?

英文:

C++ has decltype(expr). You can declare an object of type of some other expression. For example:
decltype('c') a[4] will declare an array of 4 chars. This is a toy example, but this feature can be useful. Here is some Go code for a UDP server:

conn, err := net.ListenUDP("udp", udp_addr)
...
defer conn.Close()
...
_, err = conn.WriteToUDP(data, addr)

The important thing is that I know what I can do with the (type of the) result a function (in this case, with a connection, the result of ListenUDP), but I don't know what this type is. Here, because of Go's type inference, I don't need to know. But if I want to create 5 connections, then I'd like an array of 5 "results of ListenUDP". I am not able to do that. The closest I've got is:

ret_type := reflect.TypeOf(net.DialUDP)
first_param_type := reflect.TypeOf(ret_type.Out(0))
my_arr := reflect.ArrayOf(4, first_param_type)
my_arr[0] = nil

But the last line doesn't work. Is there a way to do it in Go?

答案1

得分: 3

Go语言没有像C++的decltype那样的编译时等效功能。

但是Go是一种静态类型语言:即使在短变量声明的情况下存在类型推断,类型在编译时是已知的。net.ListenUDP()的结果类型在源代码中不可见,但你可以轻松查找,例如,将鼠标悬停在其上方2秒钟,你的IDE将显示其签名。或者在在线文档中查看。或者在终端中运行go doc net.ListenUDP

net.ListenUDP()的签名是:

func ListenUDP(network string, laddr *UDPAddr) (*UDPConn, error)

因此,用于保存返回的5个连接的数组类型是[5]*net.UDPConn。还要注意,在Go中,使用slice(切片)而不是数组更好更容易。

因此,我建议使用切片类型[]*net.UDPConn。如果你需要一个包含5个连接的切片,可以使用内置的make()函数创建,像这样:make([]*net.UDPConn, 5)

如果你真的需要在运行时动态执行此操作,那么反射可以实现。下面是一个示例:

funcType := reflect.TypeOf(net.ListenUDP)
resultType := funcType.Out(0)
arrType := reflect.ArrayOf(4, resultType)
arrValue := reflect.New(arrType).Elem()

conn := &net.UDPConn{}
arrValue.Index(0).Set(reflect.ValueOf(conn))

fmt.Println(arrValue)

这将输出(在Go Playground上尝试):

[0xc00000e058 <nil> <nil> <nil>]

相关链接:https://stackoverflow.com/questions/69518431/declare-mutiple-variables-on-the-same-line-with-types-in-go/69518670#69518670

英文:

Go does not have a compile-time equivalent to C++'s decltype.

But Go is a statically typed language: even though there's type inference in case of short variable declaration, the types are known at compile time. The result type(s) of net.ListenUDP() are not visible in the source code, but you can look it up just as easily, e.g. it takes 2 seconds to hover over it with your mouse and your IDE will display the signature. Or check online. Or run go doc net.ListenUDP in a terminal.

Signature of net.ListenUDP() is:

func ListenUDP(network string, laddr *UDPAddr) (*UDPConn, error)

So the array type to hold 5 of the returned connections is [5]*net.UDPConn. Also note that it's better and easier to use slices instead of arrays in Go.

So instead I suggest to use a slice type []*net.UDPConn. If you need a slice to hold 5 connections, you can make it using the builtin make() like this: make([]*net.UDPConn, 5).

If you really need to do this dynamically, at runtime, yes, reflection can do this. This is how it could look like:

funcType := reflect.TypeOf(net.ListenUDP)
resultType := funcType.Out(0)
arrType := reflect.ArrayOf(4, resultType)
arrValue := reflect.New(arrType).Elem()

conn := &amp;net.UDPConn{}
arrValue.Index(0).Set(reflect.ValueOf(conn))

fmt.Println(arrValue)

This will output (try it on the Go Playground):

[0xc00000e058 &lt;nil&gt; &lt;nil&gt; &lt;nil&gt;]

See related: https://stackoverflow.com/questions/69518431/declare-mutiple-variables-on-the-same-line-with-types-in-go/69518670#69518670

huangapple
  • 本文由 发表于 2022年4月20日 14:30:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/71935089.html
匿名

发表评论

匿名网友

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

确定