I'm finding the use of the blank identifier a little hard to understand. I've looked at effective go and understand most of the use cases they describe but then looking at a tutorial I came across this in a route handler function:
var person Person
_ = json.NewDecoder(req.Body).Decode(&person)
in the first line we create a new empty variable of type Person (a struct previously defined) and then I assume that
&person is passing the person var in by reference,
to be filled with data by the Decode function
this function then goes on to perform a few more tasks before encoding and returning a json response.
Why do we need have the decode assigned to a blank identifier? Couldn't we just run json.NewDecoder(req.Body).Decode(&person) ? if we can't, why not?
I'm assuming you're learning golang and asking because you can't identify why this example used this practice.
As #JimB mentioned in comments, the example writer didn't need to do this they're simply ignoring the Error return.
The blank identifier _ can be used to strictly provide the keys in a struct too. See this for reference
Without enforcing
type SomeStruct struct {
FirstField string
SecondField bool
}
myStruct := SomeStruct{"", false}
Enforcing to mention the key for the value (Removes the dependency of ordering the values)
type SomeSturct struct {
FirstField string
SecondField bool
_ struct{}
}
// COMPILATION ERROR
myStruct := SomeSturct{"", false}
The above will give the error too few values in SomeSturct literal
Related
In Go, suppose I have a []byte of UTF-8 that I want to return as a string.
func example() *string {
byteArray := someFunction()
text := string(byteArray)
return &text
}
I would like to eliminate the text variable, but Go doesn't support the following:
func example() *string {
byteArray := someFunction()
return &string(byteArray)
}
Is this second example syntax correct? And if so, why doesn't Go support it?
Because the spec defines is that way:
For an operand x of type T, the address operation &x generates a pointer of type *T to x. The operand must be addressable, that is, either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array. As an exception to the addressability requirement, x may also be a (possibly parenthesized) composite literal.
Notice that type conversions (what you are trying to do with string(byteArray)) are not included in this list.
See Marc's answer for an official citation, but here's an intuitive reason for why Go doesn't support this.
Suppose the following code
var myString string
stringPointer := &myString
*stringPointer = "some new value"
Hopefully you know, this code will write some new value into myString. This is a basic use of pointers. Now consider the modified example (pretending that it is valid code):
var myBytes []byte
// modify myBytes...
stringPointer := &string(myString)
*stringPointer = "some new value"
The question is, where in the world (or computer) are we writing to?? Where is some new value going?
In order for the language to handle this correctly, the compiler would need some internal process to "promote" the temporary value to an invisible variable, and then take the address of that. This would be adding needless complexity to make some code slightly shorter, but create this confusing situation where we have pointers with no well defined location in the program. Instead of creating these confusing ghost-variables, the language delegates to the programmer to use their own variable as usual.
I am a big fan of Golang, and very pleased to how the syntax of Go is designed. As a part of syntax philosophy, we have a rule as following: omit the things (keywords, characters etc.) if they are not needed actually.
For that reason instead of writing redundant colons:
for ; sum < 1000; {
sum += sum
}
You allowed to simply put:
for sum < 1000 {
sum += sum
}
notice how we omitted redundant semicolons
And there are lots of other cases where syntax is gratefully simplified.
But what about struct when we define type?
type Person struct {
name string
}
Why do we need to put struct keyword here?
Keywords are to determine intention, to clarify the exact choice of available options so a compiler knows how to do his job properly.
Will it be unclear and ambiguous if we simply put:
type Person {
name string
}
??
I believe there is a meaning for struct in the examples above
because compiler fails when type defined without struct keyword.
Please, explain me (and provide links) what else we can use instead of struct when we define some type.
Please, list available options from which we want to clarify to a compiler that things in curly brackets after type name are exactly parts of a struct and not something else (what else?).
Thanks.
It's not redundant. You can make types from existing types:
type MyType int
type MyType string
Or interfaces:
type Stringer interface {
String() string
}
This is covered in the Go tour and in the spec.
Types (may) not only appear in type declarations, but in countless other places, for example in function declarations.
Structs may be "used" anonymously, without creating a named type for them. For example, the following declaration is valid:
func GetPoint() struct{ x, y int } {
return struct{ x, y int }{1, 2}
}
Without having to use the struct keyword, a parsing ambiguity would arise in multiple uses. Let's say we want to create a function which returns an empty struct:
func GetEmpty() struct{} {
return struct{}{}
}
How would this look like without the struct keyword?
func GetEmpty2() {} {
return {}{}
}
Now if you're the compiler, what would you make out of this? Is this a function with the same signature as GetEmpty()? Or is this a function without a return value and an empty body (func GetEmpty2() {}) followed by a block which contains a return statement? The return statement would be another ambiguity, as it may return nothing which is followed by 2 empty blocks, or it may return an empty struct value which is followed by an empty block...
Now to avoid parsing ambiguity, we have to use the struct keyword when specifying struct types elsewhere (outside of type declarations), then why make it optional or disallow it in type declarations?
I think a consistent syntax is more important than grabbing all chances to reduce the language (syntax) to the minimum possible. That hurts readability big time. The for loop example you mentioned is not really a simplification, but rather the usage of different forms of the for loop.
I'm following up on Golang Decoding Generic JSON Objects to One of Many Formats as a way to unmarshal generic json. I'm going to have a multitude of different types tho which can be added by others, so hardcoding case statements is not feasible.
I also don't want to hardcode the type as a string, but let the ones using the library chose the "lookup" name, in case they want to rename their underlying structs later.
I am basically looking for something like this:
type myInterface interface {
Something() // irrelevant, just to show you It's not about interface{}
}
type myBar struct {} // fulfils myInterface
type mySomething struct {} // fulfils myInterface
var types = make(map[string]type) // <--- Obvious Pseudo code ;)
types["foo:bar"] = myBar // done by whoever uses the library
types["1230988"] = mySomething // ...
type storageWrapper struct {
Type string
Data json.RawMessage
}
func loadSomething(id string) myInterface {
buf := db.load(id) // pseudo code but you get the idea
sw := &storageWrapper{}
json.Unmarshal(buf, sw)
// now the interesting part
targetType := types[sw.Type]
thing := &targetType{}
json.Unmarshal(sw.Data, thing)
return thing
}
I have this feeling that I'm overthinking the whole Problem. Or that I'm trying to bend Go into something that conflicts with its underlying philosophy. I'm very open and thankful for any advice that suggests a different approach to the whole Problem
Have types be a map[string]myInterface, and to register a type, have callers store an empty value of that type (not a reference) into the map. Then, to unmarshal, you can "get the type" by copying the empty value out of the map, unmarshaling into it, and returning it (or a reference to it). The interface value will do the job of identifying which type is wanted. Plus, if users want to default some fields to non-zero/empty values in case they're not provided in the JSON, they can actually do that by storing those values within the struct in the type map.
Consider this code:
package main
import "fmt"
type specialString string
func printString(s string) {
fmt.Println(s)
}
// unlike, say, C++, this is not legal GO, because it redeclares printString
//func printString(s specialString) {
// fmt.Println("Special: " + s)
//}
func main() {
ss := specialString("cheese")
// ... so then why shouldn't this be allowed?
printString(ss)
}
My question is: why is the language defined so that the call to printString(ss) in main() is not allowed? (I'm not looking for answers that point to the Golang rules on assignment; I have already read them, and I see that both specialString and string have the same 'underlying type' and both types are 'named' -- if you consider the generic type 'string' to be named, which Golang apparently does -- and so they are not assignable under the rules.)
But why are the rules like that? What problem is solved by treating the built-in types as 'named' types, and preventing you from passing named types to all the standard library functions that accepting the same underlying built-in type? Does anybody know what the language designers had in mind here?
From my point of view, it seems to create a lot of pointless type conversion in the code, and discourages the use of strong typing where it actually would make sense..
I believe the initial authors' logic here is that named type is named for a reason - it represents something different, not just underlying type.
I guess I've read it somewhere in golang-nuts, but can't remember exact discussion.
Consider the following example:
type Email string
You named it Email, because you need to represent e-mail entity, and 'string' is just simplified representation of it, sufficient for the very start. But later, you may want to change Email to something more complex, like:
type Email struct {
Address string
Name string
Surname string
}
And that will break all your code that work with Email implicitly assuming it's a string.
This is because Go does not have class inheritance. It uses struct composition instead. Named types do not inherit properties from their underlying type (that's why it's not called "base type").
So when you declare a named type specialString with an underlying type of a predefined type string, your new type is a completely different type from the underlying one. This is because Go assumes you will want to assign different behaviors to your new type, and will not check its underlying type until run-time. This is why Go is both a static and dynamic language.
When you print
fmt.Println(reflect.TypeOf(ss)) // specialString
You get specialString, not string. If you take a look at Println() the definition is as follows:
func Println(a ...interface{}) (n int, err error) {
return Fprintln(os.Stdout, a...)
}
This means you can print any predeclared types (int, float64, string) because all of them implements at least zero methods, which makes them already conform to the empty interface and pass as "printable", but not your named type specialString which remains unknown to Go during compile time. We can check by printing the type of our interface{} against specialString.
type specialString string
type anything interface{}
s := string("cheese")
ss := specialString("special cheese")
at := anything("any cheese")
fmt.Println(reflect.TypeOf(ss)) // specialString
fmt.Println(reflect.TypeOf(s)) // string
fmt.Println(reflect.TypeOf(at)) // Wow, this is also string!
You can see that specialString keeps being naughty to its identity. Now, see how it does when passed into a function at run-time
func printAnything(i interface{}) {
fmt.Println(i)
}
fmt.Println(ss.(interface{})) // Compile error! ss isn't interface{} but
printAnything(ss) // prints "special cheese" alright
ss has become passable as interface{} to the function. By that time Go has already made ss an interface{}.
If you really want to understand deep down the hood this article on interfaces is really priceless.
It's called nominal typing. It simply means that the type is identified by it's name and it has to be made explicit to be useful.
From a convenience point of view it is easy to critique but it super useful.
For example, let's say you have a parameter to a function that is a string but it cannot be just any string, there are rules you need to check. If you change the type from string to something that implies that you checked the string for potential problems you made a good design decision because it's now clear from just looking at the code that the string needs to go via some function to validate the input first (and enrich it's type in the process).
type Validated string
func Validate(input string): (Validated, err) {
return Validated(input), nil // assuming you actually did validate the string
}
Go makes these tradeoffs because it does improve readability (i.e. the ability of someone unfamiliar with your code to quickly understand how things work) and that's something they (the Go language designers) value above all else.
I am trying to create a function that takes a []byte and an interface{} (standing for the struct) and returns an interface{} as the struct type passed into the func.
Something like this:
package main
import (
"encoding/json"
)
func UnmarshalFromJSONArray(sms []byte,tt string) (interface{}) {
var ts = new(tt)
err := json.Unmarshal(sms,&ts)
if(err != nil) {
fmt.Println(err)
}
return sms
}
So that method would run something like this:
// let's say a struct has the following definition:
type MyStructType struct {
Id int
Name string
Desc string
}
// we can some how get its fully qualified class name (this may require reflection?) or pass it into the UnMarshal method direction some how.
mst := "package.MyStructType",
// and then assume a byte array ba that has JSON format for
ba := []byte(`{"Id":"3","Name":"Jack","Desc":"the man"}`)
stct := UnmarshalFromJSONArray(ba,mst)
MyStructureType out := stct
// leaving "stct" being the unmarshalled byte array which can be used like any other struct of type "MyStructureType"
The key being that I never need to know what the fields of MyStructureType are before unmarshalling. All I need are the name of the struct and some way to instance one and then populate it with JSON byte array data that matches its fields. Hopefully that is possible (it is trivial in java using reflection). So I want to basically unmarshal an anonymous struct type by it's name without needing to know what fields it has.
Any suggestions?
The short answer is that this is impossible. There is no string to type translator in Go. You can make a map of strings to reflect.Type's, but you would need to know the possible options ahead of time or you need to provide the caller with a way to register types (perhaps in init).
Assuming you have found a way to resolve the string to its reflect.Type, you can simply call reflect.New(typ).Interface() to get the pointer you need to pass to json.Unmarshal().
The best answer is to avoid trying this all together. Writing idiomatic Java in Go isn't really possible. If I knew more about your problem, I could give you a more idiomatic Go solution.