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

Issue

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?

Solution

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 := &net.UDPConn{}
arrValue.Index(0).Set(reflect.ValueOf(conn))

fmt.Println(arrValue)

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

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

See related: Declare mutiple variables on the same line with types in Go

Answered By – icza

Answer Checked By – Katrina (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.