- They should share the same signatures, including parameter types and return types.
- They should share the same parameter types but can return different types.
- All functions should be the same type.
- The functions should not be a first class type.
User defined function types in Go (Golang)
- the number of characters
- the number of bytes
- It does not accept string types.
- the number of code points
Length of string in Go (Golang).
-
do { ... } while i < 5
-
for _,c := range "hello" { ... }
-
for i := 1; i < 5; i++ { ... }
-
for i < 5 { ... }
Explanation: Go has only for
-loops
values := []int{1, 1, 2}
-
values.append(3)
-
values.insert(3, 3)
-
append(values, 3)
-
values = append(values, 3)
Explanation: slices in GO are immutable, so calling append
does not modify the slice
const (
Write = iota
Read
Execute
)
- 0
- 1
- 2
- a random value
-
import "github/gin-gonic/gin"
-
import "https://github.com/gin-gonic/gin"
-
import "../template"
-
import "github.com/gin-gonic/gin"
package main
var GlobalFlag string
func main() {
print("["+GlobalFlag+"]")
}
- It would not compile because
GlobalFlag
was never initialized. - It would compile and print
[]
. - It would compile and print nothing because
"[" +nil+"]"
is alsonil
. - It would compile but then panic because
GlobalFlag
was never initialized.
variables in Go have initial values. For string type, it's an empty string.
Q8. From where is the variable myVar
accessible if it is declared outside of any functions in a file in package myPackage
located inside module myModule
?
- It can be accessed anywhere inside
myPackage
, not the rest of myModule. - It can be accessed by any application that imports
myModule
. - It can be accessed from anywhere in
myModule
. - It can be accessed by other packages in
myModule
as long as they importmyPackage
Explanation: to make the variable available outside of myPackage
change the name to MyVar
.
See also an example of Exported names in the Tour of Go.
-
go test
-
go test -x
-
go test --verbose
-
go test -v
type Point struct {
x int
y int
}
func main() {
data := []byte(`{"x":1, "y": 2}`)
var p Point
if err := json.Unmarshal(data, &p); err != nil {
fmt.Println("error: ", err)
} else {
fmt.Println(p)
}
}
- use
json.Decoder
- Pass a pointer to
data
- Make
X
andY
exported (uppercase) - Use field tags
- all goroutines
- any other call to lock that
Mutex
- any reads or writes of the variable it is locking
- any writes to the variable it is locking
Q12. What is an idiomatic way to pause execution of the current scope until an arbitrary number of goroutines have returned?
- Pass an
int
andMutex
to each and count when they return. - Loop over a
select
statement. - Sleep for a safe amount of time.
-
sync.WaitGroup
Explanation: this is exactly what sync.WaitGroup
is designed for - Use sync.WaitGroup in Golang
- It blocks the other channels.
- It is meant to be used in select statements without side effects.
- It blocks the
select
statement until the time has passed. - The goroutine does not end until the time passes.
Note: it doesn't block select
and does not block other channels.
- executing a function concurrently
- executing a different case based on the type of a variable
- executing a different case based on the value of a variable
- executing a different case based on which channel returns first
func Add(a, b int) {
return a + b
}
- A
// Calculate a + b
// - a: int
// - b: int
// - returns: int
func Add(a, b int) {
return a + b
}
- B
// Does a + b
func Add(a, b int) {
return a + b
}
- C
// Add returns the sum of a and b
func Add(a, b int) {
return a + b
}
- D
// returns the sum of a and b
func Add(a, b int) {
return a + b
}
Explanation: documentation block should start with a function name
-
myVal
must be an integer type, such asint
,int64
,int32
, etc. -
myVal
must be able to be asserted as anint
. -
myVal
must be an interface. -
myVal
must be a numeric type, such asfloat64
orint64
.
Explanation: This kind of type casting (using .(type)
) is used on interfaces only.
this example
Primitive types are type-casted differently
- a global variable
- a medium for sending values between goroutines
- a dynamic array of values
- a lightweight thread for concurrent programming
- Check runtime.GOOS.
- Add a // +build windows comment anywhere in the file.
- Add a _ prefix to the file name.
- Add a // +build windows comment at the top of the file.
How to use conditional compilation with the go build tool, Oct 2013
data := "A group of Owls is called a parliament"
- resp, err := http.Post("https://httpbin.org/post", "text/plain", []byte(data))
- resp, err := http.Post("https://httpbin.org/post", "text/plain", data)
- resp, err := http.Post("https://httpbin.org/post", "text/plain", strings.NewReader(data))
- resp, err := http.Post("https://httpbin.org/post", "text/plain", &data)
Q20. What should the idiomatic name be for an interface with a single method and the signature Save() error
?
- Saveable
- SaveInterface
- ISave
- Saver
- does not create; creates
- does not create; does not create
- creates; creates
- creates; does not create
Go Language Core technology (Volume one) 1.5-scope
Relevant excerpt from the article:
The second if statement is nested inside the first, so a variable declared in the first if statement is visible to the second if statement. There are similar rules in switch: Each case has its own lexical block in addition to the conditional lexical block.
- The default behavior is case insensitive, but it can be overridden.
- Fields are matched case sensitive.
- Fields are matched case insensitive.
- The default behavior is case sensitive, but it can be overridden.
Relevant excerpt from the article:
To unmarshal JSON into a struct, Unmarshal matches incoming object keys to the keys used by Marshal (either the struct field name or its tag), preferring an exact match but also accepting a case-insensitive match. By default, object keys which don't have a corresponding struct field are ignored (see Decoder.DisallowUnknownFields for an alternative).
- Time.Add() is for performing addition while Time.Sub() is for nesting timestamps.
- Time.Add() always returns a later time while time.Sub always returns an earlier time.
- They are opposites. Time.Add(x) is the equivalent of Time.Sub(-x).
- Time.Add() accepts a Duration parameter and returns a Time while Time.Sub() accepts a Time parameter and returns a Duration.
- Every field must have all tags to compile.
- It tightly couples different layers of your application.
- Any tags after the first are ignored.
- Missing tags panic at runtime.
- in the main function
- immediately after a line that might panic
- inside a deferred function
- at the beginning of a function that might panic
Example of Recover Function in Go (Golang)
Relevant excerpt from the article:
Recover is useful only when called inside deferred functions. Executing a call to recover inside a deferred function stops the panicking sequence by restoring normal execution and retrieves the error message passed to the panic function call. If recover is called outside the deferred function, it will not stop a panicking sequence.
- println(message)
- log.New(os.Stderr, "", 0).Println(message)
- fmt.Errorf("%s\n", message)
- fmt.Fprintln(os.Stderr, message)
- Use a proxy.
- Change the import path.
- Use a replace directive in go.mod.
- Use a replace directory.
Q28. If your current working directory is the top level of your project, which command will run all its test packages?
- go test all
- go run --all
- go test .
- go test ./...
Example of testing in Go (Golang)
Relevant excerpt from the article:
Relative patterns are also allowed, like "go test ./..." to test all subdirectories.
- any, it accepts arbitary bytes
- any Unicode format
- UTF-8 or ASCII
- UTF-8
Example of encoding in Go (Golang)
Relevant excerpt from the article:
Package encoding defines an interface for character encodings, such as Shift JIS and Windows 1252, that can convert to and from UTF-8.
- There is no difference.
- t.Fatal does not crash the test harness, preserving output messages.
- t.Fatal stops execution of the subtest and continues with other test cases.
- t.Fatal stops all tests and contains extra information about the failed subtest.
Explanation:
Fatal is equivalent to Log followed by FailNow.
Log formats its arguments using default formatting, analogous to Println, and records the text in the error log.
FailNow marks the function as having failed and stops its execution by calling runtime.Goexit (which then runs all deferred calls in the current goroutine). Execution will continue at the next test or benchmark. FailNow must be called from the goroutine running the test or benchmark function, not from other goroutines created during the test. Calling FailNow does not stop those other goroutines.
Run runs f as a subtest of t called name. It runs f in a separate goroutine and blocks until f returns or calls t.Parallel to become a parallel test. Run reports whether f succeeded (or at least did not fail before calling t.Parallel).
Run may be called simultaneously from multiple goroutines, but all such calls must return before the outer test function for t returns.
- It raises a panic.
- It prints the log and then raises a panic.
- It prints the log and then safely exits the program.
- It exits the program.
Example of func Fatal in Go (Golang)
Relevant excerpt from the article:
Fatal is equivalent to Print() followed by a call to os.Exit(1).
- "2006-01-02"
- "YYYY-mm-dd"
- "y-mo-d"
- "year-month-day"
Example of func Time in Go (Golang)
Relevant excerpt from the article:
Most programs can use one of the defined constants as the layout passed to Format or Parse. The rest of this comment can be ignored unless you are creating a custom layout string.
-
log.Error(err)
-
log.Printf("error: %v", err)
-
log.Printf(log.ERROR, err)
-
log.Print("error: %v", err)
Explanation: There is defined neither log.ERROR, nor log.Error() in log package; log.Print() arguments are handled in the manner of fmt.Print(); log.Printf() arguments are handled in the manner of fmt.Printf().
- any that starts with
test
- any files that include the word
test
- only files in the root directory that end in
_test.go
- any that ends in
_test.go
ch := make(chan int)
ch <- 7
val := <-ch
fmt.Println(val)
- 0
- It will deadlock
- It will not compile
- 2.718
ch := make(chan int)
close(ch)
val := <-ch
fmt.Println(val)
- It will deadlock
- It will panic
- 0
- NaN
var stocks map[string]float64 // stock -> price
price := stocks["MSFT"]
fmt.Printf("%f\n", price)
- 0
- 0.000000
- The code will panic
- NaN
- Have a cmd directory and a directory per executable inside it.
- Comment out main.
- Use build tags.
- Have a pkg directory and a directory per executable inside it.
- Set GOOS to arm64 and GOARCH to darwin.
- Set GOOS to osx and GOARCH to arm64.
- Set GOOS to arm64 and GOARCH to osx.
- Set GOOS to darwin and GOARCH to arm64.
-
go(fmt.Println("Hello Gopher!"))
-
go func() { fmt.Println("Hello Gopher!") }
-
go fmt.Println("Hello Gopher!")
-
Go fmt.Println("Hello Gopher!")
Q41. If you iterate over a map in a for range loop, in which order will the key:value pairs be accessed?
- in pseudo-random order that cannot be predicted
- in reverse order of how they were added, last in first out
- sorted by key in ascending order
- in the order they were added, first in first out
Q42. What is an idiomatic way to customize the representation of a custom struct in a formatted string?
- There is no customizing the string representation of a type.
- Build it in pieces each time by calling individual fields.
- Implement a method
String()
string - Create a wrapper function that accepts your type and outputs a string.
func findUser(ctx context.Context, login string) (*User, error) {
ch := make(chan *User)
go func() {
ch <- findUserInDB(login)
}()
select {
case user := <-ch:
return user, nil
case <-ctx.Done():
return nil, fmt.Errorf("timeout")
}
}
-
Use a sync.WaitGroup.
-
Make ch a buffered channel.
-
Add a default case to the select.
-
Use runtime.SetFinalizer.
Explanation: I am not sure, but I believe we can avoid the goroutine leak by adding a default case to the select statement. The leak happens because if the context timeout is not set correctly and if findUserInDB stalls or is slow, then the findUser function will just stay at the select statement, waiting for something to happen. We can get rid of this waiting by adding a default case, but since the function would just execute the default case every time without waiting for the goroutine, I don't believe this function would do what is intended.
var i int8 = 120 i += 10 fmt.Println(i)
- -126
- 0
- NaN
- 130
45. Given the definition of worker below, what is the right syntax to start a start a goroutine that will call worker and send the result to a channel named ch?
func worker(m Message) Result
- go func() { r := worker(m) ch <- r }
- go func() { r := worker(m) r -> ch } ()
- go func() { r := worker(m) ch <- r } ()
- go ch <- worker(m)