Is it possible to have interface composite literals in Go? - go

I just want to confirm if my understanding is correct about interface{}{}
Does interface{}{} mean a composite literal of interface type?
So, if I wanted to pass a composite type, lets say []byte as a interface{}, I should assign it to a variable of type interface{}{} and pass in that variable, whereas if I wanted to pass a non composite type, such as a int as a interface{}, I should assign it to a variable of type interface{} and pass in that variable.
Is my understanding correct on this?

interface{}{} is invalid syntax.
It is not an empty interface composite literal — there's no such thing. The following don't compile:
var a interface{}{} = "foo" // not a type
b := interface{}{} // not a value
From the specs Composite Literals:
Composite literals construct values for structs, arrays, slices, and maps and create a new value each time they are evaluated.
The valid syntax is interface{}, which is the empty interface, i.e. an interface with no name and empty method set.
If you compare it to a named interface, you will see that the extra set of curly braces at the end makes no sense:
type Fooer interface {
Foo() error
}{} // ???
You can instantiate an empty interface{} by converting nil:
a := (interface{})(nil)
Or you can declare a var of unnamed interface type:
type A struct {}
func (a A) Foo() string {
return "foo"
}
var a interface{ Foo() string } = A{}
To answer your question:
So, if I wanted to pass a composite type [...]
you can assign any value to a variable of type interface{}, that's about it. Whether the value is composite or not is irrelevant because all types satisfy the empty interface:
var a interface{} = []byte{0x01, 0x02}
var b interface{} = "string_literal"
Playground: https://play.golang.org/p/w-l1dU-6Hb5

The empty interface interface{} essentially says "I don't care". Anything can be passed as an empty interface. So for your examples they all could be stored as the empty interface.
Possibly a more interesting question is why you want to avoid types in the first place, and what you're trying to achieve. But for the purposes of using interface{} you can pass anything to it, even a "nil".

interface{} type of empty interface.
you assign []byte or int to any empty variable of empty interface (interface{} type) or you can pass it directly to function that exepts interface values.

Related

Object variables are passed into functions as interface types. Will there be implicit conversion [duplicate]

I would like to get the reflect.Kind as a reflect.Interface for a type which implements an interface but where its implementation is based on a primitive type: type id string
An alternative answer for this could be how to get any kind of reflect.Type that returns reflect.Interfaces when calling Kind().
Here is a full example on the Go Playground:
type ID interface {
myid()
}
type id string
func (id) myid() {}
func main() {
id := ID(id("test"))
fmt.Println(id)
fmt.Println(reflect.TypeOf(id))
// How to get the kind to return "reflect.Interface" from the var "id"?
fmt.Println(reflect.TypeOf(id).Kind())
}
reflect.TypeOf() (and reflect.ValueOf()) expects an interface{}. Basically whatever value you pass to reflect.TypeOf(), if it's not already an interface value, it will be wrapped in an interface{} implicitly. If the passed value is already an interface value, then the concrete value stored in it will be passed as a interface{}.
In order to avoid this "repacking", this is one of those rare cases when a pointer to interface makes sense, in fact you can't avoid it here. You have to pass a pointer to the interface value.
So if you pass a pointer to interface, this pointer will be wrapped in an interface{} value. You may use Type.Elem() to get the type descriptor of the "pointed type": that is, the element type of the pointer type, which will be the type descriptor of the interface type you're looking for.
Example:
id := ID(id("test"))
fmt.Println(id)
t := reflect.TypeOf(&id).Elem()
fmt.Println(t)
fmt.Println(t.Kind())
Which outputs (try it on the Go Playground):
test
main.ID
interface
See related question: What is the difference between reflect.ValueOf() and Value.Elem() in go?

Can I construct a slice of a generic type with different type parameters?

In the following code I have a token type that contains a literal value. By using an empty interface I can create a slice of tokens and append tokens that have different types. I don't think it's possible to accomplish the same using generics since we wouldn't be able to infer a type for the Slice of tokens. Is this assumption correct?
type Token struct {
TokenType string
Literal interface{}
}
func main(){
tok1 := &Token{TokenType: "string", Literal: "foo"}
tok2 := &Token{TokenType: "integer", Literal: 10}
tokS := []*Token{tok1, tok2}
}
No.
Given a parametrized Token type as:
type Token[T any] struct {
TokenType string
Literal T
}
each instantiation with a different type argument produces a different (named) type.
In other words, Token[string] is not assignable to Token[int]. Nor is it assignable to Token[any] as any here is used as a static type to instantiate T.
So when you construct a slice with a specific instance of Token[T any], different instances are simply not assignable to its element type:
tokS := []*Token[string]{tok1, tok2}
// invalid: cannot use tok2 (variable of type *Token[int]) as type *Token[string] in array or slice literal
The only slice that can hold different types, as Token[string] and Token[int] is []interface{} or []any.
since we wouldn't be able to infer a type for the Slice of tokens. Is this assumption correct?
Almost. More precisely, the slice of Token wouldn't infer anything because you yourself must construct it with a concrete instantiation of the generic type
Type inference is used to deduce missing type parameters from those already supplied for function arguments. Generic types must be explicitly instantiated, with a concrete type argument for each type parameter.
Is this assumption correct?
Yes. Your can have a slice of Token[string] or Token[int].

Why can't I use an empty interface that holds a concrete type of string as a return value in a function declared to return string?

I am a newcomer of go and recently I am following the instruction of A Tour of Go.
I am reading the chapter on Interface and I am really confused by the concept.
The code is as follows
package main
import "fmt"
func main() {
testTypeAssertion()
}
func testTypeAssertion() string {
var i interface{}="hello"
fmt.Printf("type of i is %T",i)
return i
// return "hello"
}
In this case, it will cause error
# example
./prog.go:12:2: cannot use i (type interface {}) as type string in return argument: need type assertion
But if I comment return i and uncomment return "hello", it goes like this
type of i is string
So why exactly do we need a type assertion here?
What's the type of i exactly?
I believe this question is different from cannot use type interface {} as type person in assignment: need type assertion. Because in that question the poster is trying to assign an empty interface value to a variable that has a concrete self-defined type person. In my question, I am trying to figure out why an interface holding a concrete string value cannot be a return value of a function whose return value type is exactly string.
Thanks to mkopriva's answer in the comment section and bugstop's answer. I will accept that it's caused by the different usage of static type and dynamic type. By the way, Reality's answer is very interesting and really helped me to understand the whole concept!
Think of an interface as a little box that holds a type and a value. The box has methods that map to methods on the value in the box.
The statement fmt.Printf("type of i is %T",i) prints the type in the box, not the type of the box itself. Reflect package trickery is required to print the type of i. but that's outside the scope of this question.
The statement return i does not compile because interface{} is not a string. The box contains a string, but the box is not a string.
We can get the value out of the box using a type assertion: return i.(string). This statement panics if i does not contain a string.
it's an interface value i with a dynamic type string.
It may be useful to read about:
How to determine an interface{} value's "real" type?
Interfaces in Go
The variable i is of type interface{}, and its value is the string "hello". An interface is simply a method-set, and since interface{} has no methods specified, all types satisfy it. Because of this, the assignment i="hello" works.
However, you cannot return an interface{} where a string is required, because string is not the same type as an interface{}. You could have returned a string where an interface{} is required, because a string implements interface{}.

Get the reflect.Kind of a type which is based on a primitive type

I would like to get the reflect.Kind as a reflect.Interface for a type which implements an interface but where its implementation is based on a primitive type: type id string
An alternative answer for this could be how to get any kind of reflect.Type that returns reflect.Interfaces when calling Kind().
Here is a full example on the Go Playground:
type ID interface {
myid()
}
type id string
func (id) myid() {}
func main() {
id := ID(id("test"))
fmt.Println(id)
fmt.Println(reflect.TypeOf(id))
// How to get the kind to return "reflect.Interface" from the var "id"?
fmt.Println(reflect.TypeOf(id).Kind())
}
reflect.TypeOf() (and reflect.ValueOf()) expects an interface{}. Basically whatever value you pass to reflect.TypeOf(), if it's not already an interface value, it will be wrapped in an interface{} implicitly. If the passed value is already an interface value, then the concrete value stored in it will be passed as a interface{}.
In order to avoid this "repacking", this is one of those rare cases when a pointer to interface makes sense, in fact you can't avoid it here. You have to pass a pointer to the interface value.
So if you pass a pointer to interface, this pointer will be wrapped in an interface{} value. You may use Type.Elem() to get the type descriptor of the "pointed type": that is, the element type of the pointer type, which will be the type descriptor of the interface type you're looking for.
Example:
id := ID(id("test"))
fmt.Println(id)
t := reflect.TypeOf(&id).Elem()
fmt.Println(t)
fmt.Println(t.Kind())
Which outputs (try it on the Go Playground):
test
main.ID
interface
See related question: What is the difference between reflect.ValueOf() and Value.Elem() in go?

How can I return a subtype of the specified return value (in this case interface{})?

I have an interface that defines one parameter to have type func(interface{}, proto.Message) interface{} and I'm trying to pass something of type func reduceMsg(a interface{}, b proto.Message) []*PersistentData to it. This results in the following compiler error:
Cannot use reduceMsg (type func(a interface{}, b proto.Message) []*PersistentData as type func(interface{}, proto.Message) interface{}
What is the reason for this error, and how can I work around it? It seems like returning a more specific type than interface{} should be legal. Here's a simple complete example that illustrates the issue:
package main
import "fmt"
func main() {
var t func() interface{} = func() []string { return []string{} }
fmt.Println(t)
}
The type of the object is the whole function signature. If the signature don't match, then it's not the same type and can't be assigned that way.
Anything can be assigned to the empty interface, because all types satisfy the interface, but in your problem neither type is the empty interface, you just have a function that returns an empty interface.
Not because a part of the function can be assigned to another it makes it the same. The type is the whole function signature. I think it's the same logic behind not being able to assign an int to an int8. You can cast them if you want, but for go, they are separate types and you need to deal with making the necessary conversions to be able to assign them.
What you can do is change your second function signature to return an empty interface like this:
func(interface{}, proto.Message) interface{}
func reduceMsg(a interface{}, b proto.Message) interface{} {
var a []*PersistentData
// do something here
return a
}
This way the function signature is the same, so it's consider the same type and you are returning an []*PersistentData. Of course you will need to do a type assertion before using it as such because the program will treat it as an {}interface because that is the type that the function returned.
Referencing the spec,
In assignments, each value must be assignable to the type of the operand to which it is assigned, with the following special cases:
Any typed value may be assigned to the blank identifier.
If an untyped constant is assigned to a variable of interface type or the blank identifier, the constant is first converted to its default type.
If an untyped boolean value is assigned to a variable of interface type or the blank identifier, it is first converted to type bool.
Assignability
A value x is assignable to a variable of type T ("x is assignable to T") in any of these cases:
x's type is identical to T.
x's type V and T have identical underlying types and at least one of V or T is not a named type.
T is an interface type and x implements T.
x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not a named type.
x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type.
x is an untyped constant representable by a value of type T.
In general, Go doesn't allow you to implicitly convert values from one type to another, with the exception of being able to use concrete-typed objects as though they were interfaces (that they implement).
In this particular case, since your function doesn't actually return an interface{}, the compiler would have to do some extra work to wrap up the return value as an interface{} and return it; if you really want to accomplish what you're trying you can do this explicitly yourself:
type Foo struct {
X int
}
func create(x int) Foo {
return Foo{X: x}
}
func main() {
var f func(int) interface{} = func(x int) interface{} {
return create(x)
}
}
which is basically doing (explicitly) the wrapping operation that you want the runtime to do implicitly.

Resources