| 10 things you (probably) don't know about Go | |
| Andrew Gerrand | |
| Gopher | |
| https://plus.google.com/106356964679457436995 | |
| @enneff | |
| https://go.dev | |
| * 1. Anonymous structs | |
| - Grouped globals | |
| var config struct { | |
| APIKey string | |
| OAuthConfig oauth.Config | |
| } | |
| config.APIKey = "BADC0C0A" | |
| - Template data | |
| data := struct { | |
| Title string | |
| Users []*User | |
| }{ | |
| title, | |
| users, | |
| } | |
| err := tmpl.Execute(w, data) | |
| (Cheaper and safer than using `map[string]interface{}`.) | |
| * 1b. Anonymous structs | |
| - Test tables | |
| var indexRuneTests = []struct { | |
| s string | |
| rune rune | |
| out int | |
| }{ | |
| {"a A x", 'A', 2}, | |
| {"some_text=some_value", '=', 9}, | |
| {"☺a", 'a', 3}, | |
| {"a☻☺b", '☺', 4}, | |
| } | |
| - Embedded lock | |
| var hits struct { | |
| sync.Mutex | |
| n int | |
| } | |
| hits.Lock() | |
| hits.n++ | |
| hits.Unlock() | |
| * 2. Nested structs | |
| - Decoding deeply nested JSON data | |
| {"data": {"children": [ | |
| {"data": { | |
| "title": "The Go homepage", | |
| "url": "https://go.dev/" | |
| }}, | |
| ... | |
| ]}} | |
| type Item struct { | |
| Title string | |
| URL string | |
| } | |
| type Response struct { | |
| Data struct { | |
| Children []struct { | |
| Data Item | |
| } | |
| } | |
| } | |
| * 3. Command-line godoc | |
| % godoc sync Mutex | |
| PACKAGE | |
| package sync | |
| import "sync" | |
| TYPES | |
| type Mutex struct { | |
| // contains filtered or unexported fields | |
| } | |
| A Mutex is a mutual exclusion lock. Mutexes can be created as part of | |
| other structures; the zero value for a Mutex is an unlocked mutex. | |
| func (m *Mutex) Lock() | |
| Lock locks m. If the lock is already in use, the calling goroutine | |
| blocks until the mutex is available. | |
| func (m *Mutex) Unlock() | |
| Unlock unlocks m. It is a run-time error if m is not locked on entry to | |
| Unlock. | |
| A locked Mutex is not associated with a particular goroutine. It is | |
| allowed for one goroutine to lock a Mutex and then arrange for another | |
| goroutine to unlock it. | |
| * 4. godoc -src | |
| % godoc -src sync Mutex | |
| // A Mutex is a mutual exclusion lock. | |
| // Mutexes can be created as part of other structures; | |
| // the zero value for a Mutex is an unlocked mutex. | |
| type Mutex struct { | |
| state int32 | |
| sema uint32 | |
| } | |
| Also shows unexported state! Great for digging around. | |
| * 5. go get supports custom domains | |
| Yep: | |
| go get camlistore.org/pkg/netutil | |
| See `go help importpath` for the details. | |
| * 6. Mock out the file system | |
| Got a package that works with the file system, but don't want your tests to actually use the disk? | |
| var fs fileSystem = osFS{} | |
| type fileSystem interface { | |
| Open(name string) (file, error) | |
| Stat(name string) (os.FileInfo, error) | |
| } | |
| type file interface { | |
| io.Closer | |
| io.Reader | |
| io.ReaderAt | |
| io.Seeker | |
| Stat() (os.FileInfo, error) | |
| } | |
| // osFS implements fileSystem using the local disk. | |
| type osFS struct{} | |
| func (osFS) Open(name string) (file, error) { return os.Open(name) } | |
| func (osFS) Stat(name string) (os.FileInfo, error) { return os.Stat(name) } | |
| Implement your own fake `fileSystem` in and put it in `fs` while testing. | |
| * 7. Method expressions | |
| type T struct {} | |
| func (T) Foo(s string) { println(s) } | |
| var fn func(T, string) = T.Foo | |
| Real example from `os/exec`: | |
| func (c *Cmd) stdin() (f *os.File, err error) | |
| func (c *Cmd) stdout() (f *os.File, err error) | |
| func (c *Cmd) stderr() (f *os.File, err error) | |
| type F func(*Cmd) (*os.File, error) | |
| for _, setupFd := range []F{(*Cmd).stdin, (*Cmd).stdout, (*Cmd).stderr} { | |
| fd, err := setupFd(c) | |
| if err != nil { | |
| c.closeDescriptors(c.closeAfterStart) | |
| c.closeDescriptors(c.closeAfterWait) | |
| return err | |
| } | |
| c.childFiles = append(c.childFiles, fd) | |
| } | |
| * 8. Send and receive on the same channel | |
| .play 10things/8.go | |
| * 9. Using close to broadcast | |
| .play 10things/9.go /func.waiter/,/endmain/ | |
| * 9b. Using close to broadcast | |
| .play 10things/9b.go /func.worker/,/endmain/ | |
| * 10. Nil channel in select | |
| .play 10things/10.go /func.worker/,/endmain/ | |
| * 11. The gopher's name | |
| .image 10things/gopher.jpg | |