How does golang do this? [duplicate] - go

This question already has an answer here:
Is this casting in golang?
(1 answer)
Closed 7 months ago.
After having issues understanding and being unable to access the ClusterComputeResourceSummary.UsageSummary field while working with govmomi, I was able to find a link that helped solve my problem, however, I am curious to understand how Golang is doing this behind the scenes, how after a chaining dot you provide the type you must obviously know before hand to extract the object and its properties?
usage := resource.Summary.(*types.ClusterComputeResourceSummary).UsageSummary
How can I go about reading this syntax, especially the part after .(*types.ClusterComputeResourceSummary) ?
P.S. Forgive me for the question title, honestly I don't know the right term or lingo for this use case, like is this reflection or something similar?

This is a "type assertion". The resource.Summary is an interface value that contains a pointer to an object, and its type. The type assertion checks if the type you gave *types.ClusterComputeResourcesSummary can be assigned to the type of data stored in the interface, and if so, returns the value stored in the interface as an instance of that type. Then you can access the members/methods of that variable.

Related

In go language, may I define allowed values of a string in a struct and/or force creation only via constructor? Or avoid direct creation of a struct? [duplicate]

This question already has answers here:
Creating a Constant Type and Restricting the Type's Values
(2 answers)
What is an idiomatic way of representing enums in Go?
(14 answers)
Closed 8 months ago.
I have a struct Direction with a value of type string. Direction should be N, S, W or E.
type Direction struct {
value string
}
Inspired by an answer of this question: Does Go have "if x in" construct similar to Python? I guess a good way to create Direction in a valid manner can be this one:
func NewDirection(direction string) Direction {
switch direction {
case "N","S","W","E": return Direction{direction}
}
panic("invalid direction")
}
But this is not enough for me because I can still create invalid Direction:
d := Direction{"X"}
I also found this interesting article about enforcing the use of constructor in go. Reading this article I can see that is necessary the usage of another package. May I have a "protected" struct in, for example, main package?
You've already done almost everything you should do by convention:
make the field unexported
provide a constructor
put a comment on the type stating that the constructor should be used, and explain how zero-values are treated (if that matters)
Now users of the package can't modify the field, and the existence of the constrictor makes it clear that it should be called to create valid instances. This is the convention that is set by the standard library.
Sure, there are other ways that you can make it even harder to invalidate values but this is essentially just wasting time and overcomplicating your code for the sake of an unwinnable arms race against an imaginary opponent.
If someone doesn't understand the language and doesn't read documentation, then they're always going to find a way to misuse it. If they are actively trying to sabotage themselves, there's nothing you can do to stop them and no reason to either.
Packages are the smallest functional unit of code organization in Go. There is no way to protect field at, for example, the file level. Even files within the same package effectively operate as if all their code was in the same file. Therefore, any code in the same package as the constructor will have the same privileges as the constructor.

What's the difference between generic and non-generic use of interfaces? [duplicate]

This question already has answers here:
What are the benefits of replacing an interface argument with a type parameter?
(2 answers)
Closed 8 months ago.
In the new Type Parameters Design Draft, you can now apply an interface constraint to a generic function:
func prettyPrint[T Stringer](s T) string {
...
}
But, this was already possible by using an interface parameter without generics:
func prettyPrint(s Stringer) string {
...
}
What's the difference between using the first and using the second?
I assume the question refers to the latest draft of the Type Parameters proposal, which may end up in Go in 1.18.
The first is parametric polymorphism. The compiler verifies that the constraint is satisfied, and then generates code that takes a statically-known type. Importantly, it's not boxed.
The second is runtime polymorphism. It takes a type that's unknown at compile time (the only thing known is that it implements the interface) and works on a boxed interface pointer.
Performance considerations aside, in this simple case you can use either approach. Generics really help with the more complicated cases where the current tools don't work well.

GoLang: Semantic Meaning of a Property Wrapped in Parenthesis? [duplicate]

This question already has answers here:
What is this "err.(*exec.ExitError)" thing in Go code? [duplicate]
(2 answers)
What is the meaning of "dot parenthesis" syntax? [duplicate]
(1 answer)
Closed 5 years ago.
Go Newb here -- I've encountered the following bit of Go code that I didn't write
if tc, ok := tng.(ThingClasser); ok {
//... do some stuff ...
}
I won't understand the semantics of tng.(ThingClasser).
In some ways this looks like a method call -- i.e. there are two variables (ec, ok) sitting there ready to accept multiple return values.
However, tng.(ThingClasser) itself looks like its a property access, not a method call.
However however, the parens around ThingClasser are a wrinkle I've never seen before. Also, if it matters, the ThingClasser symbol is defined elsewhere in this project as an interface, so I think maybe this is some syntactic sugar around an does this implement an interface -- but then the two return values confused me.
Googling hasn't turned up anything concrete, but this is one of those hard things to google for.
Does anyone here know what this call/syntax is in GoLang, and possible point me at the relevant manual pages so I can RTFM?
It's a type assertion. The returned values are 1) the object, converted to the given type; and 2) a boolean indicating if the conversion was successful. ThingClasser is the type being converted to. Documentation can be found here: https://golang.org/ref/spec#Type_assertions

golang cast to relfect.Type [duplicate]

This question already has answers here:
golang type assertion using reflect.Typeof()
(6 answers)
Closed 7 years ago.
My Problem is as follows:
I have a slice of reflect.Value, that was returned from a MethodByName("foo").Call().
now i want to cast the contained values to their types, which i dont know statically, but in form of relflect.Type
Basically what i want to do is:
values[0].Interface().(mytype)
but with reflection
values[0].Interface().(reflect.TypeOf(responseObject))
This gives me the compilation error:
reflect.TypeOf(responseObject) is not a type
Is there a way to do this in go?
Thanks and regards
BillDoor
If you have code using the normal type assertion syntax like:
x := v.(mytype)
Then the compiler knows that the variable x is of type mytype, and generates code accordingly. If the language let you use an expression in place of the type, then the compiler would have no way of knowing what type x is, and consequently no way to generate code that uses that variable.
If you only know the type of value at runtime, then you will need to stick with the reflect.Value API. You can determine the value's type using its Type method, and there are methods that will let you access struct fields, indexes in slices or arrays, etc.
You will only be able to move back to regular syntax when you have a type you know about at compile time.
What is a cast (type assertion)? It has two effects:
At compile time, the compile-time of the whole type assertion expression is the type casted to.
At runtime, a check is made on the actual runtime type of the value, and if it is not the type casted to, it will generate a runtime error.
Obviously, #1 doesn't make sense for a type that is not known at compile-time, because how can the compile-time type of something depend on something not known at compile time?
You can still do manually do #2 for a type that is not known at compile time. Just get the runtime type of the value using reflect.TypeOf() and compare it against the runtime.Type you have.

Variable declaration shortcut outside of function [duplicate]

This question already has answers here:
Why isn't short variable declaration allowed at package level in Go?
(3 answers)
Closed 8 years ago.
Coming from a background in Java and C# I am very pleased with the brevity of Golang's ability to use the shortcut method for variable declaration for private variables within functions, which allows me to write:
x := 1.5
It reminds me of duck typing in a dynamic language such as Python. However, in declaring global variables outside of the scope of a function you still need to use the more verbose syntax of:
var x float64 = 1.5
I'm just wondering why the shortcut method works for private variables and not globals? I know that the designers of the language are quite experienced so I'm assuming that this isn't reflective of a feature overlooked. Is there a technical reason why this kind of type inference (and I realize that the := shortcut is not the same as proper type inference) wouldn't work at the global scope? It just seems somewhat inconsistent in terms of the design, and as an inexperienced Gopher I must admit to being thrown off by this on a couple of occasions. On the whole however I'm really enjoying Go.
See the Ian's answer in this thread:
https://groups.google.com/forum/#!msg/golang-nuts/qTZemuGDV6o/IyCwXPJsUFIJ
At the top level, every declaration begins with a keyword. This
simplifies parsing.
Actually you don't need to specify type in many cases.
var x = 1.5
should work fine. It's probably as short as it can get and it's not much longer than local variable shortcut.
So there is a shortcut for global.
As to why := can't be used, I would guess that calling out var makes code structure more consistent as other global constructs start with a keyword - func, const, import, type.

Resources