Go's Hidden Pragmas

Go's Hidden Pragmas
展开查看详情

1.Go’s Hidden #pragmas GopherChina 2017

2. @davecheney Go programmer from Sydney, Australia

3.But first, a history lesson.

4. Perl use strict;
 use strict "vars";
 use strict "refs";
 use strict "subs";
 use strict;
 no strict "vars";

5. Javascript "use strict";

6. Rust #[inline(always)]
 fn super_fast_fn() { #[cfg(target_os = "macos")]
 mod macos_only {

7.Warning: History time

8.ALGOL 68 pragmat

9. C #pragma pack(2) 
 struct T {
 int i; 
 short j;
 double k;
 };

10.Does Go have pragmas?

11.Yes. Go has pragmas //

12. They're actually called pragmas in the source

13. syscall/syscall_linux_amd64.go //go:noescape
 func gettimeofday(tv *Timeval) (err Errno)

14.cmd/compile/internal/gc/testdata/arith.go //go:noinline
 func lshNop1(x uint64) uint64 {
 // two outer shifts should be removed
 return (((x << 5) >> 2) << 2)
 }

15. runtime/atomic_pointer.go //go:nosplit
 func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) {
 writebarrierptr_prewrite((*uintptr)(ptr), uintptr(new))
 atomic.StorepNoWB(noescape(ptr), new)
 }

16.A word of caution
 🚨

17. "Useful" is always true for a feature request. The question is, does the usefulness justify the cost? The cost here is continued proliferation of magic comments, which are becoming too numerous already. –Rob Pike

18.//go:noescape

19. Escape Analysis func NewBook() *Book {
 b := Book{Mice: 12, Men: 9}
 return &b
 }

20. Escape Analysis (cont.) func BuildLibrary() {
 b := Book{Mice: 99: Men: 3}
 AddToCollection(&b)
 }

21.Answer: it depends
 🤔

22. b does not escape func AddToCollection(b *Book) {
 b.Classification = "fiction"
 }

23. b escapes var AvailableForLoan []*Book func AddToCollection(b *Book) {
 AvailableForLoan = append(AvailableForLoan, b)
 }

24. os.File.Read f, _ := os.Open("/tmp/foo")
 buf := make([]byte, 4096)
 n, _ := f.Read(buf)

25. os.File.Read // Read reads up to len(b) bytes from the File.
 // It returns the number of bytes read and any error encountered.
 // At end of file, Read returns 0, io.EOF.
 func (f *File) Read(b []byte) (n int, err error) {
 if err := f.checkValid("read"); err != nil {
 return 0, err
 }
 n, e := f.read(b)
 if e != nil {
 if e == io.EOF {
 err = e
 } else {
 err = &PathError{"read", f.name, e}
 }
 }
 return n, err
 }

26. golang.org/issue/4099 commit fd178d6a7e62796c71258ba155b957616be86ff4
 Author: Russ Cox <rsc@golang.org>
 Date: Tue Feb 5 07:00:38 2013 -0500 cmd/gc: add way to specify 'noescape' for extern funcs A new comment directive //go:noescape instructs the compiler
 that the following external (no body) func declaration should be
 treated as if none of its arguments escape to the heap. Fixes #4099. R=golang-dev, dave, minux.ma, daniel.morsing, remyoudompheng, adg, agl, iant
 CC=golang-dev
 https://golang.org/cl/7289048

27. bytes.IndexByte (circa Go 1.5) package bytes //go:noescape
 // IndexByte returns the index of the first instance of c in s,
 // or -1 if c is not present in s.
 func IndexByte(s []byte, c byte) int // ../runtime/asm_$GOARCH.s

28.Can you use //go:noescape in your code?

29.//go:norace