Production Go. Build modern, production-ready systems in Go (Herman Schaaf, Shawn Smith) (z-library.sk, 1lib.sk, z-lib.sk)

Author: Herman Schaaf, Shawn Smith

GO

If you are reading this book, we assume you are interested in running Go in a production environment. Maybe you dabble in Go on your side projects, but are wondering how you can use it at work. Or perhaps you’ve read a company blog post about converting their codebase to Go, which now has 3 times less code and response times one tenth of what they were before. Your mileage will vary when it comes to gains in productivity and efficiency, but we think they will be positive gains. Our goal in writing this book is to provide the knowledge to write a production-ready service in Go. This means not only writing the initial implementation, but also reliably deploying it, monitoring its performance, and iterating on improvements. Go is a language that allows for fast iteration, which goes well with continuous deployment. Although Go is a statically typed language, it compiles quickly and can often be used as a replacement for scripting languages like Python. And many users report that when writing Go, once a program works, it continues to “just work”. We suspect that this is due to the simple design of the language, and the focus on readability rather than clever constructs. In one project, we replaced existing APIs in PHP with equivalent functionality in Go. We saw performance improvements, including an order of magnitude reduction in response times, which led to both higher user retention and a reduction in server costs. We also saw developer happiness increase, because the safety guarantees in Go reduced the number of production-breaking bugs. This book is not meant for beginner programmers. We expect our audience to be knowledgeable of basic computer science topics and software engineering practices. Over the years, we have helped ramp up countless engineers who had no prior experience writing Go. Ideally this will be the book that people recommend to engineers writing Go for the first time, and who want to better understand the “right way” to write Go. We hope this book

📄 File Format: PDF
💾 File Size: 1.3 MB
5
Views
0
Downloads
0.00
Total Donations

📄 Text Preview (First 20 pages)

ℹ️

Registered users can read the full content for free

Register as a Gaohf Library member to read the complete e-book online for free and enjoy a better reading experience.

📄 Page 1
(This page has no text content)
📄 Page 2
Production Go Build modern, production-ready systems in Go Herman Schaaf and Shawn Smith This book is for sale at http://leanpub.com/productiongo This version was published on 2018-11-03 This is a Leanpub book. Leanpub empowers authors and publishers with the Lean Publishing process. Lean Publishing is the act of publishing an in-progress ebook using lightweight tools and many iterations to get reader feedback, pivot until you have the right book and build traction once you do. © 2013 - 2018 Herman Schaaf and Shawn Smith
📄 Page 3
Contents Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . i Getting Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Installing Go . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 GOPATH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Editor Integrations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Linters and Correctness Tooling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Program Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Variables and Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Basic Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 Structs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Conditional Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 Slices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Exported Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 Goroutines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Channels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 Error Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 Reading Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 Writing Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 Style and Error Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Style . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Error Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
📄 Page 4
CONTENTS Wrapping Up . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 Appending to Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 Splitting strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 Counting and finding substrings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Advanced string functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Ranging over a string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Supporting Unicode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 A very brief history of string encodings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 Strings are byte slices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 Printing strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Runes and safely ranging over strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 Handling right-to-left languages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 sync.WaitGroup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 Channels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 Goroutines in web handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 Pollers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Race conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 Why do we need tests? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 Writing Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 Testing HTTP Handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 Mocking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 Generating Coverage Reports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 Writing Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Benchmarks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 A simple benchmark . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 Comparing benchmarks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 Resetting benchmark timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 Benchmarking memory allocations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 Modulo vs Bitwise-and . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 Tooling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 Godoc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 Go Guru . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 Race Detector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 Go Report Card . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
📄 Page 5
CONTENTS CSRF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 Content Security Policy (CSP) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 HTTP Strict Transport Security (HSTS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 bluemonday (https://github.com/microcosm-cc/bluemonday) . . . . . . . . . . . . . . . . . . 128 Continuous Integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 The build . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 Deployment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 Monitoring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 Prometheus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 Optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 Common Gotchas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 Nil interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 Licenses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
📄 Page 6
Introduction Why Go in Production? If you are reading this book, we assume you are interested in running Go in a production environment. Maybe you dabble in Go on your side projects, but are wondering how you can use it at work. Or perhaps you’ve read a company blog post about converting their codebase to Go, which now has 3 times less code and response times one tenth of what they were before. Your mileage will vary when it comes to gains in productivity and efficiency, but we think they will be positive gains. Our goal in writing this book is to provide the knowledge to write a production-ready service in Go. This means not only writing the initial implementation, but also reliably deploying it, monitoring its performance, and iterating on improvements. Go is a language that allows for fast iteration, which goes well with continuous deployment. Although Go is a statically typed language, it compiles quickly and can often be used as a replacement for scripting languages like Python. And many users report that when writing Go, once a program works, it continues to “just work”. We suspect that this is due to the simple design of the language, and the focus on readability rather than clever constructs. In one project, we replaced existing APIs in PHP with equivalent functionality in Go. We saw performance improvements, including an order of magnitude reduction in response times, which led to both higher user retention and a reduction in server costs. We also saw developer happiness increase, because the safety guarantees in Go reduced the number of production-breaking bugs. This book is not meant for beginner programmers. We expect our audience to be knowledgeable of basic computer science topics and software engineering practices. Over the years, we have helped ramp up countless engineers who had no prior experience writing Go. Ideally this will be the book that people recommend to engineers writing Go for the first time, andwhowant to better understand the “right way” to write Go. We hope this book will help guide you on your journey to running Go in production. It will cover all important aspects of running a production system, including advanced topics like profiling the memory usage of a Go program, deploying andmonitoring apps written in Go, andwriting idiomatic tests. Feel free to skip around to chapters that seemmore relevant to your immediate concerns or interests. We will do our best to keep the chapters fairly independent of one another in order to make that possible.
📄 Page 7
Getting Started “Clear is better than clever” - Rob Pike
📄 Page 8
Installing Go Installation The Go Downloads page¹ contains binary distributions of Go for Windows, Apple macOS, or Linux. You can also find instructions for installing Go from source on their Installing Go from source² page. We recommend installing a binary release first, as there are some extra steps necessary to install from source, and you really only need to install from source if you’re planning to contribute changes upstream to the Go language itself. Also, if you use Homebrew on macOS, you should be able to install go with a simple brew install go. Once installed, test the command by running: $ go version and you should see something like: go version go1.9 darwin/amd64 GOPATH Once you’ve installed Go, you need to set up a workspace. Traditionally this is called the GOPATH, but since Go 1.8 there is a default workspace at $HOME/go on Unix and %USERPROFILE%/go on Windows (for the sake of brevity, we’re going to assume you’re using UNIX and only refer to $HOME/go from now on). You’ll have to create this directory if it doesn’t already exist. This is where you’ll be writing most if not all of your Go code. Typically you’ll be working with Go packages that are hosted on GitHub. When you retrieve a package using the go get command, the source will be automatically downloaded into your workspace. For example, if you want to download the popular URL router library gorilla/mux³, you would run: go get github.com/gorilla/mux and the source of that library will be downloaded into $HOME/go/src/github.com/gorilla/mux. You can now also import that library in your own code. Here’s an example based on some sample code from the gorilla/mux README: ¹https://golang.org/dl/ ²https://golang.org/doc/install/source ³https://github.com/gorilla/mux
📄 Page 9
Installing Go 3 1 package main 2 3 import ( 4 "fmt" 5 "net/http" 6 7 "github.com/gorilla/mux" 8 ) 9 10 func HomeHandler(w http.ResponseWriter, r *http.Request) { 11 fmt.Fprintf(w, "Hello, world") 12 } 13 14 func main() { 15 r := mux.NewRouter() 16 r.HandleFunc("/", HomeHandler) 17 http.Handle("/", r) 18 http.ListenAndServe(":8080", r) 19 } Note the import of "github.com/gorilla/mux" at the top. Editor Integrations Since there are so many editors and IDEs out there, we will only briefly cover three common editors: Goland by JetBrains, vim and Sublime Text. We will link to relevant information for other popular editors at the end of the section. For all editors, we recommend running goimports on save. Similar to the gofmt command, goimports formats your Go code, but it also automatically adds or removes imports according to what is referenced in the code. If you reference mux.NewRouter in your code but have not yet imported github.com/gorilla/mux, goimports will find the package and import it. It also works for the standard library, which is especially useful for times when you want to call fmt.Println but don’t feel like importing fmtmanually (or when you remove a fmt.Println and don’t feel like deleting the import). It is worthwhile exploring the plugins available for your editor to make sure this is working: it will greatly speed up your Go development process. Goimports can be installed with go get:
📄 Page 10
Installing Go 4 1 go get golang.org/x/tools/cmd/goimports We now discuss some useful plugins for three common editors, in (arguably!) decreasing order of complexity. GoLand GoLand is a powerful and mature IDE for Go. It features code completion, the ability to jump to variable and type definitions, standard debugging tools like run-time inspection and setting break points, and more. A free 30-day trial can be downloaded from https://www.jetbrains.com/go/ Once installed, we recommend installing goimports on save. To do this, go to File -> Settings -> Tools -> File Watchers. Click the Plus (+) icon, and select “goimports”. Press OK. When you now save a Go file in the project, it should get formatted according to Go standards automatically. Sublime Text For Sublime Text 3, we recommend installing a package called GoSublime⁴. This is done via Sublime Text package control. Package control can be installed with the commands provided at https://packagecontrol.io/installation. Once installed, open package control by pressing Ctrl+Shift+P on Windows and Linux, or Cmd+Shift+P on OS X. Then type “install package” and select “Package control: install package”. Now type “GoSublime” and choose the matching option. Finally, open the GoSublime settings by going to Preferences -> Package Settings -> GoSublime -> Settings-User. Make sure that GOPATH matches the path you configured earlier. Here are some typical settings: 1 { 2 // you may set specific environment variables here 3 // e.g "env": { "PATH": "$HOME/go/bin:$PATH" } 4 // in values, $PATH and ${PATH} are replaced with 5 // the corresponding environment(PATH) variable, if it exists. 6 "env": {"GOPATH": "$HOME/Code/go", "PATH": "$GOPATH/bin:$PATH" }, 7 8 "fmt_cmd": ["goimports"] 9 } vim For vim, you will want to install vim-go⁵. Instructions can be found on that page for the various vim package managers. ⁴https://github.com/DisposaBoy/GoSublime ⁵https://github.com/fatih/vim-go
📄 Page 11
Installing Go 5 Once you have installed vim-go, you can add the following line to your .vimrc file in order to run goimports on save: let g:go_fmt_command="goimports" Linters and Correctness Tooling If you want to install a suite of linters and tools to run on your code, we recommend gometalinter⁶. To install: $ go get -u github.com/alecthomas/gometalinter $ gometalinter --install Gometalinter allows you to run a variety of linters and tooling and conveniently combines all of their output into a standard format. We’ve found the deadcode, ineffassign, and misspell (disabled by default, enable with --enable=misspell) to be particularly useful. If you don’t want to install all of the linters available, you can install them individually instead. For misspell for example, install with: $ go get -u github.com/client9/misspell/cmd/misspell Gometalinter should automatically pick up that you have misspell installed and you’ll be able to do: $ gometalinter --deadline=180s --exclude=vendor --disable-all --enable=misspell ./... While you may not want to require some of these linters to pass in your build, one tool we recommend requiring is go vet⁷. Go vet is a tool concerned with code correctness. It will find problems in your code such as using the wrong string formatting verb in a call to Printf: 1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 func main() { 8 fmt.Printf("%d", "test") 9 } This code compiles and runs, but if you do actually run it you’ll see this: ⁶https://github.com/alecthomas/gometalinter ⁷https://golang.org/cmd/vet/
📄 Page 12
Installing Go 6 $ go run main.go %!d(string=test)% because %d is meant for printing integers, not strings. If you were to run go vet on the above code, you would see this warning: $ go vet main.go main.go:8: arg "test" for printf verb %d of wrong type: string exit status 1 Another common issue vet will catch for you is the use of printf verbs inside a call to Println: 1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 func main() { 8 fmt.Println("%d", "test") 9 } Again this will compile and run fine, but the output would be this: $ go run main.go %d test Calling go vet on this code will tell you: $ go vet main.go main.go:8: possible formatting directive in Println call exit status 1
📄 Page 13
Basics This chapter gives a quick run-through of Go’s basic syntax, and the features that differentiate it from other languages. If you have never programmed in Go before, this chapter will give you the knowledge to start reading and writing simple Go programs. Even if you have programmed in Go before, we recommend that you still read this chapter. Through the examples, we will highlight common pitfalls in Go programs, and answer some of the questions that even experienced Go programmers might still have. Program Structure Go code is organized in packages containing one or more Go source files. When building an executable, we put our code into a package main with a single func main. As mentioned in the Installation chapter, our Go code lives in GOPATH, which we’re saying is $HOME/go. Let’s say we want to write our first Go command, which randomly selects an item from a list and outputs it to stdout.We need to create a directory in our GOPATH, with a main.go file containing a package main and single main function: $ mkdir -p $GOPATH/src/github.com/prodgopher/dinner $ cd $GOPATH/src/github.com/prodgopher/dinner In this directory we’ll add our main.go with the following code: Random dinner selection 1 package main 2 3 import ( 4 "fmt" 5 "math/rand" 6 "time" 7 ) 8 9 func main() { 10 dinners := []string{ 11 "tacos", 12 "pizza",
📄 Page 14
Basics 8 13 "ramen", 14 } 15 rand.Seed(time.Now().Unix()) 16 fmt.Printf("We'll have %s for dinner tonight!\n", dinners[rand.Intn(len(dinn\ 17 ers))]) 18 } We can run our code with go run main.go. The other option is to build our code as an executable and run that. To do that, we first run go build to make sure that the code compiles. Then we run go install: $ go build $ go install $ cd $GOPATH/bin $ ./dinner We'll have pizza for dinner tonight! We can also run these commands from outside of our GOPATH, like so: $ go build github.com/prodgopher/dinner $ go install github.com/prodgopher/dinner If we want to expose this functionality in a package so we can reuse it in other places, we need to add this functionality to a package. Let’s say we just want to return the name of the dinner, rather than the whole string, like “pizza”, “ramen”, etc. For convenience, let’s reuse the same github.com/prodgopher/dinner directory. Remove the main.go file and create a new dinner.go file that looks like this: Random dinner selection package 1 package dinner 2 3 import ( 4 "math/rand" 5 "time" 6 ) 7 8 func Choose() string { 9 dinners := []string{ 10 "tacos", 11 "pizza",
📄 Page 15
Basics 9 12 "ramen", 13 } 14 rand.Seed(time.Now().Unix()) 15 16 return dinners[rand.Intn(len(dinners))] 17 } Now, somewhere outside of our dinner package directory (let’s just use our home folder), we’ll invoke our new functionality in a file called main.go: Using our random dinner selection package 1 package main 2 3 import ( 4 "fmt" 5 6 "github.com/prodgopher/dinner" 7 ) 8 9 func main() { 10 fmt.Println(dinner.Choose()) 11 } $ go run main.go tacos Now we have a convenient package for randomly selecting what to eat for dinner. Variables and Constants There are multiple ways to declare variables in Go. The first way, declaring a var with a given type, can be done like so: var x int With this type of declaration, the variable will default to the type’s zero value, in this case 0. Another way to declare a variable is like this:
📄 Page 16
Basics 10 var x = 1 Similar to the above method, but in this case we can declare the specific contents. The type is also implied. Lastly, the short-hand variable declaration: x := 1 This is probably the most common way, and the type is also implied like the above. Sometimes the var declaration method is used stylistically to indicate that the variable will be changed soon after the declaration. For example: 1 var found bool 2 for _, x := range entries { 3 if x.Name == "Gopher" { 4 found = true 5 } 6 } One key difference between var and := declarations is that the shorthand version (:=) cannot be used outside of a function, only var can. This means that variables in the global scope must be declared using var. This is valid: Example using var to declare variable in global scope 1 package main 2 3 import "fmt" 4 5 var a = 1 6 7 func main() { 8 fmt.Println(a) 9 } but this will not compile:
📄 Page 17
Basics 11 It is invalid to use shorthand variable declaration in the global scope 1 package main 2 3 import "fmt" 4 5 a := 1 // this is invalid, use var instead 6 7 func main() { 8 fmt.Println(a) 9 } Running the above, we get the following error: $ go run var_bad.go # command-line-arguments ./var_bad.go:5: syntax error: non-declaration statement outside function body The other subtle difference between var-declarations and shorthand-declarations occur when declaring multiple variables. The following code is valid, 1 var a, b = 0, 1 // declare some variables 2 b, c := 1, 2 // this is okay, because c is new 3 fmt.Println(a, b, c) // Outputs: 0, 1, 2 but this is not valid: 1 var a, b = 0, 1 // declare some variables 2 var b, c = 1, 2 // this is not okay, because b already exists 3 fmt.Println(a, b, c) The second example, when placed into a program, fails to compile: ./var_shorthand_diff2.go:7: b redeclared in this block previous declaration at ./var_shorthand_diff2.go:6 This is because the shorthand := may redeclare a variable if at least one of the variables to its left is new. The var declaration may not redeclare an existing variable.
📄 Page 18
Basics 12 Basic Data Types Basic Types Go supports the following basic types: • bool • string • int8, int16, int32, int64, int • uint8, uint16, uint32, uint64, uint • float32, float64 • complex64, complex128 • byte (alias for uint8) • rune (alias for int32) Booleans The bool type represents a boolean and is either true or false. Usage of booleans in Go 1 package main 2 3 import "fmt" 4 5 func main() { 6 a, b := true, false 7 c := a && b 8 d := a || b 9 10 fmt.Println("a:", a) 11 fmt.Println("b:", b) 12 fmt.Println("c:", c) 13 fmt.Println("d:", d) 14 15 // Output: a: true 16 // b: false 17 // c: false 18 // d: true 19 }
📄 Page 19
Basics 13 In the above example we first create a and b, and assign them the values true and false, respectively. c is assigned the value of the expression a && b. The && operator returns true when both a and b are true, so in this case c is false. The || operator returns true when either a or b are true, or both. We assign d the value of a || b, which evaluates to true. Note that unlike some other languages, Go does not define true or false values for data types other than bool. Strings The string type represents a collection of characters. When defined in code, a string is a piece of text surrounded by double quotes ("). Let’s write a simple program using strings. Usage of booleans in Go 1 package main 2 3 import "fmt" 4 5 func main() { 6 sound := "meow" 7 sentence := "The cat says " + sound + "." 8 fmt.Println(sentence) 9 } The example demonstrates that strings support the + operator for concatenation. The variable sentence contains a concatenation of the strings "The cat says ", “meow”, and ”.”. When we print it to the screen, we get The cat says meow.‘ This just scratches the surface of strings in Go. We will discuss strings in more depth in the chapter on Strings. Integers The integer types can be divided into two classes, signed and unsigned. Signed integers The signed integer types are int8, int16, int32, int64, and int. Being signed, these types store both negative and positive values, but up to a maximum half the value of its uint counterpart. int8 uses 8 bits to store values between -128 and 127 (inclusive). int16 stores values in the range -32,768 to 32,767. int32 stores values in the range -2,147,483,648 to 2,147,483,647. int64 stores values in the range -2⁶³ to 2⁶³-1, which is to say, between -9,223,372,036,854,775,808 and 9,223,372,036,854,775,807.
📄 Page 20
Basics 14 Unlike the other signed integer types, the int type does not explicitly state its width. This is because it acts as an alias for either int32 or int64, depending on the architecture being compiled to. This means that it will perform optimally on either architecture, and it is the most commonly used integer type in Go code. Go does not allow implicit type conversions. When converting between integer types, an explicit type cast is required. For example, see the following code: Type mixing that will result in a compile-time error 1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 func main() { 8 var i32 int32 = 100 9 var i64 int64 = 100 10 11 // This will result in a compile-time error: 12 fmt.Println(i32 + i64) 13 } This results in a compile-time error: 1 $ go run type_mix.go 2 type_mix.go:12:18: invalid operation: i32 + i64 (mismatched types int32 and i\ 3 nt64) To fix the error, we can either use the same types from the start, or do a type cast. We will discuss type casts again later in this chapter, but here is how we might use a type cast to solve the problem: Using an integer type cast 1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 func main() { 8 var i32 int32 = 100
The above is a preview of the first 20 pages. Register to read the complete e-book.

💝 Support Author

0.00
Total Amount (¥)
0
Donation Count

Login to support the author

Login Now
Back to List