Reputation: 13908
I found this example here:
func(*myHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
// What does this line do??
if h, ok := route[request.URL.String()]; ok {
h(writer, request)
return
}
io.WriteString(writer, "my server: " + request.URL.String())
}
I am extremely puzzled by this line:
if h, ok := route[request.URL.String()]; ok { h(writer, request) }
first off, how can it be valid syntactically to declare ok
after it is assigned to the result of route()
?
second, if h
is returned by route()
, how can it be used in the definition of ok
???
I am thoroughly confused by this. Gophers, please help.
Upvotes: 1
Views: 112
Reputation: 124648
Take a look at this page in Tour of Go. It explains that:
Like
for
, theif
statement can start with a short statement to execute before the condition.
Given your example:
h, ok := route[request.URL.String()]; ok { ... }
The short statement is h, ok := route[request.URL.String()]
. The ;
after marks the end of the short statement. The ok
that follows is the condition. If true, then the code block {...}
is executed. In that code block you can use all the variables that were assigned in the short statement.
first off, how can it be valid syntactically to declare
ok
after it is assigned to the result ofroute()
?
ok
is not declared after it is assigned. It is a boolean value, used in the condition.
second, if
h is returned by
route(), how can it be used in the definition of
ok`???
It's not definition of ok
. It's the code block of the if
statement.
Consider this alternative, almost equivalent writing style:
h, ok := route[request.URL.String()]
if ok {
h(writer, request)
return
}
This is perfectly clear, right? We just split the original code to two steps. But this is not the same. When writing this way, the h
and ok
variables are visible after the if
statement. This is not desirable. It's a good practice to minimize the visibility of variables (also known as the live time). The longer a variable is visible, the longer the window of vulnerability during which it can be accidentally misused. This syntax of Go is truly great, genius, and I don't know a single other language where this kind of if
statement is possible.
See also the section on the if
statement in Effective Go.
Upvotes: 4
Reputation: 24250
Firstly: you should run through the Go Tour - specifically the section on Maps: https://tour.golang.org/moretypes/16
The "comma, ok" idiom here is designed to check that the key exists in the map. Doing a lookup on a non-existent key will panic (and likely crash your application).
if h, ok := route[request.URL.String()]; ok { h(writer, request) }
request.URL.String()
exists, set h
and set ok
to true.ok
is true, then call the function h
.Upvotes: 3