├── .gitignore ├── README.md ├── basic-types ├── Basic Types.key ├── Basic Types.pdf ├── Basic Types.pptx ├── README.md ├── bool │ └── main.go ├── byte │ └── main.go ├── complex │ └── main.go ├── exercise │ └── main.go ├── float │ └── main.go ├── int │ └── main.go ├── rune │ └── main.go ├── string │ ├── interpreted.go │ ├── main.go │ ├── raw.go │ └── underlying-structure.go ├── uint │ └── main.go └── uintptr │ └── main.go ├── constants ├── Constants.key ├── Constants.pdf ├── Constants.pptx ├── README.md ├── blank-identifier │ ├── filename.txt │ └── main.go ├── c-vs-go │ ├── exec │ ├── main.c │ └── main.go ├── default-kind-types │ └── main.go ├── high-precision │ └── main.go ├── implicit-type-conversion │ ├── by-syntax.go │ └── by-type.go ├── iota │ └── main.go ├── kind-promotion │ └── main.go ├── overflow │ └── main.go ├── scope │ ├── main.go │ ├── p1 │ │ └── p1.go │ └── p2 │ │ └── p2.go ├── strings │ └── main.go └── types │ └── main.go ├── custom-import-path ├── Custom import path.key ├── Custom import path.pdf ├── Custom import path.pptx ├── README.md ├── custom-path │ ├── main.go │ └── server.go └── import-path-checking │ ├── README.md │ └── main.go ├── custom-package-manager ├── Custom package manger.key ├── README.md └── pkg-manager │ ├── downloader.go │ ├── go-pkg.json │ ├── main.go │ └── manager.go ├── go-commands.md ├── go-environment-variables └── README.md ├── go-learning-resources ├── Go Resources.key ├── Go Resources.pdf ├── Go Resources.pptx └── README.md ├── go-module-proxy ├── Go module proxy.key └── README.md ├── go-modules ├── @latest │ └── main.go ├── Go modules.key ├── README.md ├── basic-http │ └── main.go ├── download │ └── main.go ├── go-mod-tidy │ └── main.go ├── go111module │ └── main.go ├── incompatible-pkg-versions │ └── main.go ├── migration-from-dep │ └── main.go ├── outside-gopath │ └── main.go └── vendor-directory │ └── main.go ├── go-program-anatomy ├── Go program anatomy.key ├── Go program anatomy.pdf ├── Go program anatomy.pptx ├── README.md ├── go-build │ ├── bip_darwin_386.go │ ├── bip_darwin_amd64.go │ ├── bip_linux_386.go │ ├── bip_linux_amd64.go │ ├── good-bye-darwin-386.go │ ├── good-bye-darwin-amd64.go │ ├── good-bye-linux-386.go │ ├── good-bye-linux-amd64.go │ ├── greet_darwin.go │ ├── greet_linux.go │ ├── main.go │ ├── welcome-linux.go │ └── welcome-osx.go ├── program-flow │ ├── main.go │ ├── pkg1 │ │ └── pkg1.go │ ├── pkg2 │ │ └── pkg2.go │ └── pkg3 │ │ └── pkg3.go └── runtime-vs-buildtime │ └── main.go ├── go-workspace.md ├── gophertuts.svg ├── internal-directory ├── Internal directory.key └── README.md ├── number-systems ├── Number systems.key ├── Number systems.pdf ├── Number systems.pptx └── README.md ├── package-management ├── Package management.key ├── README.md ├── basic-http │ ├── Gopkg.lock │ ├── Gopkg.toml │ ├── app │ │ └── app.go │ ├── config │ │ ├── config.go │ │ └── config.yaml │ ├── controllers │ │ ├── index.go │ │ ├── people.go │ │ └── routes.go │ ├── logging │ │ └── logger.go │ └── main.go ├── cmd-directory │ └── main.go ├── custom-library │ ├── internal │ │ └── pkg.go │ └── main.go ├── dep │ └── main.go ├── glide │ └── main.go ├── go-mod │ └── main.go ├── internal-directory │ └── main.go ├── package-archives │ └── main.go ├── private-packages │ └── main.go ├── semver │ └── main.go └── vendor-directory │ └── main.go ├── packages ├── Packages.key ├── Packages.pdf ├── Packages.pptx ├── README.md ├── cross-reference │ ├── main.go │ ├── p1 │ │ └── p1.go │ └── p2 │ │ └── p2.go ├── exported-vs-unexported │ ├── main.go │ └── pkg │ │ └── pkg.go ├── go-get │ ├── README.md │ ├── go.mod │ ├── go.sum │ └── main.go ├── locals-vs-globals │ ├── main.go │ └── square.go ├── multiple-packages │ ├── main.go │ ├── pkgA.go │ └── pkgB.go ├── package-naming │ ├── anotherWeirdPkg │ │ └── another-weird.go │ ├── collision │ │ └── collision.go │ ├── main.go │ ├── redundant │ │ └── redundant.go │ ├── right │ │ └── wrong.go │ └── weird_long_package_name_with_underscores │ │ └── weird.go ├── package-organization │ ├── controllers │ │ ├── c1.go │ │ ├── c1_test.go │ │ ├── c2.go │ │ ├── c2_test.go │ │ ├── controllers.go │ │ └── controllers_test.go │ └── main.go ├── package-types │ ├── main.go │ └── services │ │ └── s1.go └── test-packages │ ├── pkg1 │ ├── pkg1.go │ └── pkg1_test.go │ └── pkg2 │ ├── pkg2.go │ └── pkg2_test.go └── vendor-directory ├── README.md ├── Vendor directory.key ├── Vendor directory.pdf ├── Vendor directory.pptx ├── main.go ├── pkg1 └── pkg1.go ├── pkg2 └── pkg2.go ├── pkg3 └── pkg3.go └── vendor └── github.com ├── gophertuts └── go-basics │ └── vendor-directory │ └── pkg3 │ └── pkg3.go └── julienschmidt └── httprouter └── router.go /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea/ 3 | **/vendor 4 | !vendor-directory/vendor/ 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # go-basics 2 | 3 | ## Go language basics 4 | 5 | This section includes exercises and small projects which illustrate the basics of Go programming language. Things such as: types, data structures, functions, pointers, packages and others. 6 | 7 | ## Section overview 8 | 9 | - [Go Learning Resources](https://github.com/gophertuts/go-basics/blob/master/go-learning-resources) 10 | - [Go Program Anatomy](https://github.com/gophertuts/go-basics/blob/master/go-program-anatomy) 11 | - [Number Systems](https://github.com/gophertuts/go-basics/blob/master/number-systems) 12 | - [Basic Types](https://github.com/gophertuts/go-basics/blob/master/basic-types) 13 | - [Constants](https://github.com/gophertuts/go-basics/blob/master/constants) 14 | - [Packages](https://github.com/gophertuts/go-basics/blob/master/packages) 15 | - [Vendor directory](https://github.com/gophertuts/go-basics/blob/master/vendor-directory) 16 | - [Custom import paths](https://github.com/gophertuts/go-basics/blob/master/custom-import-paths) 17 | - [Custom package manager](https://github.com/gophertuts/go-basics/blob/master/custom-package-manager) 18 | - [Package Management](https://github.com/gophertuts/go-basics/blob/master/package-management) 19 | - [Go modules](https://github.com/gophertuts/go-basics/blob/master/go-modules) 20 | - [Go module proxy](https://github.com/gophertuts/go-basics/blob/master/go-module-proxy) 21 | - [Internal directory](https://github.com/gophertuts/go-basics/blob/master/internal-directory) 22 | 23 | ### Installation 24 | 25 | Before trying any of these examples make sure to have the `Go` binary installed on your platform. 26 | 27 | OSX: 28 | 29 | ```bash 30 | # Install Homebrew 31 | 32 | /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 33 | ``` 34 | 35 | ```bash 36 | # Install Go 37 | 38 | brew install go 39 | ``` 40 | 41 | Linux: 42 | 43 | ```bash 44 | # Move into $HOME directory 45 | cd ~ 46 | 47 | # Download the binary for your distribution 48 | curl -O https://dl.google.com/go/go1.12.linux-amd64.tar.gz 49 | 50 | # Verify that the downloaded binary is not corrupted. Check if the hash matches the one from downloads page 51 | sha256sum go1.12.linux-amd64.tar.gz 52 | 53 | # Extract the binary 54 | tar xvf go1.12.linux-amd64.tar.gz 55 | 56 | # Make root user the owner of Go workspace 57 | sudo chown -R root:root ./go 58 | 59 | # Move go directory to a standard location 60 | sudo mv go /usr/local 61 | ``` 62 | 63 | For more details regarding `Go` installation check out 64 | 65 | [Golang Installation](https://golang.org/doc/install) 66 | 67 | For downloading `Go` binary for your platform checkout 68 | 69 | [Golang Downloads](https://golang.org/dl/) 70 | 71 | To check if you installed `Go` successfully type: 72 | 73 | ```bash 74 | # Displays installed Go version 75 | go version 76 | 77 | # Displays all environment variables defined by Go 78 | go env 79 | ``` 80 | 81 | Docker: 82 | 83 | ```bash 84 | docker run -it golang:1.11 85 | ``` 86 | 87 | ### Set $GOPATH variable 88 | ```bash 89 | sudo nano ~/.profile 90 | 91 | # Linux 92 | export GOPATH=/usr/local/go 93 | export GOBIN=$GOPATH/bin 94 | export PATH=$PATH:/$GOBIN 95 | 96 | # OSX 97 | export GOPATH=$HOME/go 98 | export GOBIN=$GOPATH/bin 99 | export PATH=$PATH:/$GOBIN 100 | 101 | # Save File 102 | 103 | # Restart shell configuration 104 | source ~/.profile 105 | ``` 106 | 107 | ### Other Go tools 108 | 109 | You can also install other `Go` tools which will help you have a more productive development process 110 | 111 | - [Go Tools](https://github.com/golang/tools) 112 | - [Go Lint](https://github.com/golang/lint) 113 | - [Go Imports](https://godoc.org/golang.org/x/tools/cmd/goimports) 114 | 115 | #### Go Tools 116 | 117 | ```bash 118 | go get -u golang.org/x/tools/... 119 | ``` 120 | 121 | #### Go Lint 122 | 123 | ```bash 124 | go get -u golang.org/x/lint/golint 125 | ``` 126 | 127 | #### Go Imports 128 | 129 | ```bash 130 | go get -u golang.org/x/tools/cmd/goimports 131 | ``` 132 | 133 | #### Daily routine things 134 | 135 | - Format your entire code recursively using 136 | `go fmt ./...` 137 | 138 | - Lint your entire code recursively using 139 | `golint ./...` 140 | 141 | ### For more info about Go check out 142 | 143 | [Go Doc](https://golang.org/pkg) 144 | 145 | [Go Packages](https://godoc.org/) 146 | 147 | [Go Playground](https://play.golang.org/) 148 | 149 | [Effective Go](https://golang.org/doc/effective_go.html) 150 | 151 | [A Tour of Go](https://tour.golang.org/) 152 | 153 | 154 | ### For more info about Go commands & WORKSPACE check out 155 | 156 | [Go commands explained](https://github.com/gophertuts/go-basics/blob/master/go-commands.md) 157 | 158 | [Go WORKSPACE explained](https://github.com/gophertuts/go-basics/blob/master/go-workspace.md) 159 | 160 | ## FEEDBACK ⚗ 161 | 162 | [GopherTuts TypeForm](https://feedback.gophertuts.com) 163 | 164 | ## COMMUNITY 🙌 165 | 166 | [GopherTuts Discord](https://discord.gg/4sgecdh) 167 | 168 | --- 169 | 170 | Happy hacking gophers 🚀🚀🚀 171 | 172 | -------------------------------------------------------------------------------- /basic-types/Basic Types.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/basic-types/Basic Types.key -------------------------------------------------------------------------------- /basic-types/Basic Types.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/basic-types/Basic Types.pdf -------------------------------------------------------------------------------- /basic-types/Basic Types.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/basic-types/Basic Types.pptx -------------------------------------------------------------------------------- /basic-types/README.md: -------------------------------------------------------------------------------- 1 | # Basic Types in Go 2 | 3 | ## Overall types discussed in this tutorial: 4 | 5 | - bool 6 | - int 7 | - int8 8 | - int16 9 | - int32/rune 10 | - int64 11 | - int64 12 | - uint 13 | - uint8/byte 14 | - uint16 15 | - uint32 16 | - uint64 17 | - uint64 18 | - uintptr 19 | - float32 20 | - float64 21 | - complex64 22 | - complex128 23 | - string 24 | 25 | Note: `int`, `uint`, `uintptr`, `string` sizes are platform dependent 26 | In case you want to simulate x32 or x64 platform architecture 27 | follow the instructions below 28 | 29 | ## Simulate x32 / x64 bit architecture 30 | 31 | ```bash 32 | # cd into the project i.e. int examples 33 | cd $GOPATH/src/github.com/gophertuts/go-basics/basic-types/int 34 | 35 | # 32bit 36 | env GOARCH=386 go run main.go 37 | 38 | # 64bit 39 | env GOARCH=amd64 go run main.go 40 | 41 | # $GOARCH => $GOHOSTARCH will be taken 42 | go run main.go 43 | 44 | # to check you host architecture run 45 | go env | grep GOHOSTARCH 46 | ``` 47 | 48 | ## Resources 💎 49 | 50 | - [String implementation](https://github.com/golang/go/blob/master/src/runtime/string.go) 51 | - [Strings - Go101](https://go101.org/article/string.html) 52 | - [Unsafe package](https://golang.org/pkg/unsafe/) 53 | - [Unsafe - Go101](https://go101.org/article/unsafe.html) 54 | - [UintPtr vs Unsafe pointer](https://utcc.utoronto.ca/~cks/space/blog/programming/GoUintptrVsUnsafePointer) 55 | - [Complex numbers](https://en.wikipedia.org/wiki/Complex_number) 56 | - [Floating point numbers](https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) 57 | - [IEEE standard 754](https://www.geeksforgeeks.org/ieee-standard-754-floating-point-numbers/) 58 | - [How are floating numbers stored in memory](https://stackoverflow.com/questions/7644699/how-are-floating-point-numbers-stored-in-memory) 59 | - [How to normalize a mantissa](https://stackoverflow.com/questions/28800565/how-to-normalize-a-mantissa) 60 | 61 | 62 | ## Related tutorials 63 | - [Number systems](https://github.com/gophertuts/go-basics/blob/master/number-systems) 64 | 65 | ## FEEDBACK ⚗ 66 | 67 | [GopherTuts TypeForm](https://gophertuts.typeform.com/to/j2CJmC) 68 | 69 | ## COMMUNITY 🙌 70 | 71 | [GopherTuts Discord](https://discord.gg/4sgecdh) 72 | 73 | --- 74 | 75 | Back to 76 | [Go Basics](https://github.com/gophertuts/go-basics) 77 | 78 | 79 | -------------------------------------------------------------------------------- /basic-types/bool/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | const num = 10 9 | 10 | func main() { 11 | fmt.Println(unsafe.Sizeof(true)) 12 | fmt.Println(unsafe.Sizeof(false)) 13 | fmt.Println(unsafe.Sizeof(1 > 10)) 14 | fmt.Println(unsafe.Sizeof(!true)) 15 | if num > 3 { 16 | fmt.Println(`"num" is greater than 3`) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /basic-types/byte/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | const ( 9 | b1 byte = 1 10 | b3 byte = 255 // if greater than 255: const will overflow byte 11 | ) 12 | 13 | var ( 14 | b2 byte = 'A' 15 | ) 16 | 17 | func main() { 18 | fmt.Printf("%T\n", b1) 19 | fmt.Println(unsafe.Sizeof(b1)) 20 | fmt.Println("uint value", b2, "string value", string(b2)) 21 | fmt.Println(b3) 22 | // automatic conversion to 'uint8' 23 | fmt.Printf("value of: A + B = %[1]v | type: %[1]T\n", 'A'+b2) 24 | // no conversion is done, falling back to 'int32' aka 'rune' 25 | fmt.Printf("value of: A + B = %[1]v | type: %[1]T\n", 'A'+'B') 26 | } 27 | -------------------------------------------------------------------------------- /basic-types/complex/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | var ( 9 | c64 complex64 = 12 10 | c128 complex128 = 128 11 | c128_2 = 3i 12 | c128_3 = +0i 13 | c64_2 complex64 = 3 + 15 14 | ) 15 | 16 | func main() { 17 | fmt.Printf("size: %d | type %T\n", unsafe.Sizeof(c64), c64) 18 | fmt.Printf("size: %d | type %T\n", unsafe.Sizeof(c128), c128) 19 | fmt.Printf("size: %d | type %T\n", unsafe.Sizeof(c128_2), c128_2) 20 | fmt.Printf("size: %d | type %T\n", unsafe.Sizeof(c128_3), c128_3) 21 | fmt.Printf("size: %d | type %T\n", unsafe.Sizeof(c64_2), c64_2) 22 | fmt.Println(unsafe.Sizeof(1 + 2i)) // 128b => 16B 23 | fmt.Println(11 + 25.3*4 + 4i) // real part - 112.2 | imaginary part - 4i 24 | fmt.Println(4i) // real part - 0 | imaginary part - 4i 25 | } 26 | -------------------------------------------------------------------------------- /basic-types/exercise/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | // 你 - 3B 7 | // 好 - 3B 8 | // " " - 1B 9 | s := []byte("你 好") 10 | if len(s) == 3 { 11 | fmt.Println("String has 3 Bytes") 12 | } else { 13 | fmt.Println("String has 7 Bytes") 14 | } 15 | fmt.Println(len(s)) 16 | } 17 | -------------------------------------------------------------------------------- /basic-types/float/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | var ( 9 | f32 float32 = 5 // automatic conversion to float32 10 | f64 float64 = 13 // automatic conversion to float64 11 | f64_2 = 13.2 // automatic conversion to float64 12 | ) 13 | 14 | func main() { 15 | fmt.Printf("size: %d | type %T\n", unsafe.Sizeof(f32), f32) 16 | fmt.Printf("size: %d | type %T\n", unsafe.Sizeof(f64), f64) 17 | fmt.Printf("size: %d | type %T\n", unsafe.Sizeof(f64_2), f64_2) 18 | fmt.Printf("size: %d | type %T\n", unsafe.Sizeof(.2), .2) 19 | fmt.Printf("size: %d | type %T\n", unsafe.Sizeof(12.5), 12.5) 20 | fmt.Printf("value: %[1]v | type: %[1]T\n", 2*3.0) // conversion to float64 21 | fmt.Printf("value: %[1]v | type: %[1]T\n", 14/3) // no conversion is done 22 | } 23 | -------------------------------------------------------------------------------- /basic-types/int/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | const ( 9 | i8 int8 = -128 10 | ) 11 | 12 | var ( 13 | i64 int64 = 12.0 // default conversion to int64 14 | i32 = int32(i64) // explicit conversion to int32 15 | f64 = 12.5 16 | i64_2 = int64(f64) // explicit conversion to int64 17 | c = 'A' // rune = int32 18 | r rune = 'B' 19 | ) 20 | 21 | func main() { 22 | fmt.Printf("size: %d | type %T\n", unsafe.Sizeof(i64), i64) 23 | fmt.Printf("size: %d | type %T\n", unsafe.Sizeof(c), c) 24 | fmt.Printf("size: %d | type %T\n", unsafe.Sizeof(r), r) 25 | fmt.Println(i8) 26 | fmt.Println(unsafe.Sizeof(10)) // 32b/64b => 4/8B 27 | } 28 | -------------------------------------------------------------------------------- /basic-types/rune/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | var ( 9 | r1 = 65 10 | r2 = 'Z' 11 | r3 rune = 128 12 | ) 13 | 14 | func main() { 15 | fmt.Printf("size: %d | type %T\n", unsafe.Sizeof('A'+'B'), 'A'+'B') 16 | fmt.Printf("size: %d | type %T\n", unsafe.Sizeof(r3), r3) 17 | fmt.Printf("some char range regex: [%s-%s]\n", string(r1), string(r2)) 18 | fmt.Println("Your order total is of 100", string(r3)) 19 | } 20 | -------------------------------------------------------------------------------- /basic-types/string/interpreted.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | const interpreted = "This text is interpreted\n\n \tsome tabulated text\nand a special char '\u0028'" 6 | 7 | func main() { 8 | fmt.Println(interpreted) 9 | } 10 | -------------------------------------------------------------------------------- /basic-types/string/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | var ( 9 | rs = []rune{'W', 'e', 'l', 'c', 'o', 'm', 'e', '好'} 10 | bs = []byte{'W', 'e', 'l', 'c', 'o', 'm', 'e', '!'} 11 | ) 12 | 13 | func main() { 14 | s := "Hello World" 15 | // a string is just a slice of bytes or a sequence of uint8(s) 16 | fmt.Printf("%T\n", s[0]) 17 | // check out the underlying string structure 18 | fmt.Println(unsafe.Sizeof(s)) // 64/128b 19 | 20 | // explicit conversion to string 21 | fmt.Println(string(rs)) 22 | fmt.Println(string(bs)) 23 | } 24 | -------------------------------------------------------------------------------- /basic-types/string/raw.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | const raw = ` 6 | 7 | 8 | 9 | 10 | 12 | 13 | Document 14 | 15 | 16 | 17 | ` 18 | 19 | func main() { 20 | fmt.Println(raw) 21 | } 22 | -------------------------------------------------------------------------------- /basic-types/string/underlying-structure.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | // underlying string type 9 | // check out the implementation 10 | // https://github.com/golang/go/blob/master/src/runtime/string.go 11 | // https://github.com/golang/go/blob/master/src/runtime/string.go#L224 12 | type _string struct { 13 | // 4B/8B => 32/64b - depending on GOARCH 14 | elements *byte // underlying bytes 15 | // 4B/8B => 32/64b - depending on GOARCH 16 | len int // number of bytes 17 | } 18 | 19 | func main() { 20 | var b byte 21 | var pb *byte 22 | s := "Hello World" 23 | fmt.Println(unsafe.Sizeof(_string{})) // 8/16B => 64/128b 24 | fmt.Println(unsafe.Sizeof(pb)) // 4/8B => 64b 25 | fmt.Println(unsafe.Sizeof(b)) // 4/8B => 64b 26 | fmt.Println(unsafe.Sizeof(s)) // 8/16B => 128b 27 | } 28 | -------------------------------------------------------------------------------- /basic-types/uint/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | const ( 9 | uInt8 int8 = 127 10 | ) 11 | 12 | var ( 13 | greatestUint32 = ^uint32(0) 14 | greatestUint64 = ^uint64(0) 15 | uInt64 uint64 = 12.0 // default conversion to int64 16 | uInt32 = int32(uInt64) // explicit conversion to int32 17 | f64 = 12.5 18 | uInt64V2 = int64(f64) // explicit conversion to int64 19 | c = 'A' // rune = int32 20 | r rune = 'B' 21 | ) 22 | 23 | func main() { 24 | fmt.Println(greatestUint32) 25 | fmt.Println(greatestUint64) 26 | fmt.Printf("size: %d | type %T\n", unsafe.Sizeof(uInt64), uInt64) 27 | fmt.Printf("size: %d | type %T\n", unsafe.Sizeof(uInt32), uInt32) 28 | fmt.Printf("size: %d | type %T\n", unsafe.Sizeof(uInt64V2), uInt64V2) 29 | fmt.Printf("size: %d | type %T\n", unsafe.Sizeof(c), c) 30 | fmt.Printf("size: %d | type %T\n", unsafe.Sizeof(r), r) 31 | fmt.Println(uInt8) 32 | fmt.Println(unsafe.Sizeof(10)) // 32b/64b => 4/8B 33 | } 34 | -------------------------------------------------------------------------------- /basic-types/uintptr/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | i := 10 10 | 11 | ptr1 := unsafe.Pointer(&i) 12 | fmt.Println(*(*int)(ptr1)) 13 | 14 | uptr1 := uintptr(i) 15 | uptr1 += 20 16 | 17 | ptr2 := unsafe.Pointer(&uptr1) 18 | fmt.Println(*(*int)(ptr2)) 19 | } 20 | -------------------------------------------------------------------------------- /constants/Constants.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/constants/Constants.key -------------------------------------------------------------------------------- /constants/Constants.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/constants/Constants.pdf -------------------------------------------------------------------------------- /constants/Constants.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/constants/Constants.pptx -------------------------------------------------------------------------------- /constants/README.md: -------------------------------------------------------------------------------- 1 | # Constants in Go 2 | 3 | ## Types of const(s) 4 | 5 | - Typed 6 | - Untyped (Kind) 7 | 8 | ## Facts about constants 9 | 10 | - Cannot be reassigned or redeclared 11 | - Can only hold scalar values 12 | - Can hold large high precision numbers 13 | - Can be created from expression of other constants 14 | - Can be untyped (Kind) 15 | - Constants only **exist** during **compilation time** 16 | 17 | ## C background 18 | 19 | #### How to run the C program 20 | 21 | ```bash 22 | # cd into the project directory 23 | cd $GOPATH/src/github.com/gophertuts/go-basics/constants/c-vs-go 24 | 25 | # compile the program 26 | gcc main.c -o exec 27 | 28 | # run the program 29 | ./exec 30 | ``` 31 | 32 | ## Resources 💎 33 | 34 | - [Constants](https://blog.golang.org/constants) 35 | - [Basic Kind](https://golang.org/pkg/go/types/#Basic.Kind) 36 | - [Iota](https://github.com/golang/go/wiki/Iota) 37 | - [Identifiers](https://golang.org/ref/spec#Identifiers) 38 | - [Keywords](https://golang.org/ref/spec#Keywords) 39 | - [Numeric types](https://golang.org/ref/spec#Numeric_types) 40 | - [Representability](https://golang.org/ref/spec#Representability) 41 | - [Constant expressions](https://golang.org/ref/spec#Constant_expressions) 42 | - [Introduction to Numeric Constants](https://www.ardanlabs.com/blog/2014/04/introduction-to-numeric-constants-in-go.html) 43 | - [A Tour of Go - Basics](https://tour.golang.org/basics/1) 44 | 45 | ## FEEDBACK ⚗ 46 | 47 | [GopherTuts TypeForm](http://feedback.gophertuts.com) 48 | 49 | ## COMMUNITY 🙌 50 | 51 | [GopherTuts Discord](https://discord.gg/4sgecdh) 52 | 53 | --- 54 | 55 | Back to 56 | [Go Basics](https://github.com/gophertuts/go-basics) 57 | 58 | 59 | -------------------------------------------------------------------------------- /constants/blank-identifier/filename.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/constants/blank-identifier/filename.txt -------------------------------------------------------------------------------- /constants/blank-identifier/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | // unused import 5 | _ "fmt" 6 | // package side effects (like init) 7 | _ "github.com/go-sql-driver/mysql" 8 | "log" 9 | "os" 10 | ) 11 | 12 | // unused const identifier 13 | const ( 14 | _ = 10 15 | ) 16 | 17 | func main() { 18 | // unused (ignored) error value 19 | f, _ := os.Open("filename.txt") 20 | log.Print(f.Name()) 21 | } 22 | -------------------------------------------------------------------------------- /constants/c-vs-go/exec: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/constants/c-vs-go/exec -------------------------------------------------------------------------------- /constants/c-vs-go/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | unsigned int u = 1e9; 5 | long signed int i = 1; 6 | // warning: format specifies type 'int' but the argument has type 'long' [-Wformat] 7 | printf("Result: %d\n", i + u); 8 | } 9 | -------------------------------------------------------------------------------- /constants/c-vs-go/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | const ( 6 | u uint = 1e9 7 | i int = 1 8 | ) 9 | 10 | func main() { 11 | // invalid operation: i + u (mismatched types int and uint) 12 | //fmt.Println("Result", i+u) 13 | fmt.Println("Result1", uint(i) + u) 14 | fmt.Println("Result2", int(u) + i) 15 | } 16 | -------------------------------------------------------------------------------- /constants/default-kind-types/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | const ( 6 | // untyped bool - bool 7 | b = false 8 | 9 | // untyped int - int 10 | i = 12 11 | 12 | // untyped int - int 13 | j = iota 14 | 15 | // untyped rune - int32 16 | c = 'N' 17 | 18 | // untyped float - float64 19 | f = 3.5 20 | e = 1e+200 21 | 22 | // untyped complex - complex128 23 | cx = 3 + 4i 24 | 25 | // untyped string - string 26 | s = "Hello World" 27 | ) 28 | 29 | func main() { 30 | fmt.Printf("b: %T\n", b) 31 | fmt.Printf("i: %T\n", i) 32 | fmt.Printf("j: %T\n", j) 33 | fmt.Printf("c: %T\n", c) 34 | fmt.Printf("f: %T\n", f) 35 | fmt.Printf("e: %T\n", e) 36 | fmt.Printf("cx: %T\n", cx) 37 | fmt.Printf("s: %T\n", s) 38 | } 39 | -------------------------------------------------------------------------------- /constants/high-precision/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | const ( 8 | // constants are only available during compile time 9 | Pi = 3.14159265358979323846264338327950288419716939937510582097494459 10 | HugeMathematicallyExact = 36893488147419103230 11 | MaxUint = 18446744073709551615 12 | //MaxUint = ^uint(0) 13 | ) 14 | 15 | func main() { 16 | fmt.Println(Pi) //3.141592653589793 17 | fmt.Println(3.141592653589793 / Pi) // 0.9999999999999999 18 | 19 | // constant 36893488147419103230 overflows int 20 | //fmt.Println(uint(HugeMathematicallyExact)) 21 | fmt.Println(HugeMathematicallyExact / MaxUint) // 2 22 | } 23 | -------------------------------------------------------------------------------- /constants/implicit-type-conversion/by-syntax.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type T complex128 6 | 7 | const t T = 1 8 | 9 | func main() { 10 | fmt.Printf("Value: %+v | Type: %T\n", 10, 10) 11 | fmt.Printf("Value: %+v | Type: %T\n", ^3, ^3) 12 | fmt.Printf("Value: %+v | Type: %T\n", 10 > 2, 10 > 2) 13 | fmt.Printf("Value: %+v | Type: %T\n", 1<<7, 1<<7) 14 | fmt.Printf("Value: %+v | Type: %T\n", 'A', 'A') 15 | fmt.Printf("Value: %+v | Type: %T\n", 11.2, 11.2) 16 | fmt.Printf("Value: %+v | Type: %T\n", 1e+15, 1e+15) 17 | fmt.Printf("Value: %+v | Type: %T\n", 1e-10, 1e-10) 18 | fmt.Printf("Value: %+v | Type: %T\n", .2, .2) 19 | fmt.Printf("Value: %+v | Type: %T\n", 12i, 12i) 20 | fmt.Printf("Value: %+v | Type: %T\n", "hello", "hello") 21 | fmt.Printf("Value: %+v | Type: %T\n", 1+2.5, 1+2.5) 22 | fmt.Printf("Value: %+v | Type: %T\n", 2/3, 2/3) 23 | fmt.Printf("Value: %+v | Type: %T\n", 10/2.0, 10/2.0) 24 | fmt.Printf("Value: %+v | Type: %T\n", 24./12, 24./12) 25 | fmt.Printf("Value: %+v | Type: %T\n", 1+13.2/t*5i-'D', 1+13.2/t*5i-'D') 26 | } 27 | -------------------------------------------------------------------------------- /constants/implicit-type-conversion/by-type.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | var ( 6 | i int = 13.0 7 | f float64 = 5 8 | c complex128 = 12.3 + 5 9 | ) 10 | 11 | func main() { 12 | fmt.Printf("Value: %+v | Type: %T\n", i, i) 13 | fmt.Printf("Value: %+v | Type: %T\n", f, f) 14 | fmt.Printf("Value: %+v | Type: %T\n", c, c) 15 | } 16 | -------------------------------------------------------------------------------- /constants/iota/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | // week days 6 | const ( 7 | Sunday = iota + 1 8 | Monday 9 | Tuesday 10 | Wednesday 11 | Thursday 12 | Friday 13 | Saturday 14 | ) 15 | 16 | // byte multiples 17 | const ( 18 | // first value is ignored (we do not want 0) 19 | _ = iota 20 | KB = 1 << (iota * 10) 21 | MB 22 | GB 23 | TB 24 | PB 25 | ) 26 | 27 | func main() { 28 | fmt.Println("Week days:") 29 | fmt.Println(Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday) 30 | 31 | fmt.Println("Byte multiples:") 32 | fmt.Println(KB, MB, GB) 33 | } 34 | -------------------------------------------------------------------------------- /constants/kind-promotion/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type T complex128 8 | 9 | const ( 10 | t T = 1 11 | // keep the order in mind, the last from this list has the top priority in the end result type 12 | // integer, rune, floating-point, complex, string, custom type 13 | n = 2 + t*'c'*2.0 + 35i 14 | shift = 'c' << 5 15 | ) 16 | 17 | func main() { 18 | fmt.Printf("%T\n", n) 19 | fmt.Printf("%T", shift) 20 | } 21 | -------------------------------------------------------------------------------- /constants/overflow/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | ) 7 | 8 | const Huge = 1.2676506002282294e+30 9 | 10 | func main() { 11 | // int32 12 | fmt.Println(^int32(math.Pow(2, 31))) // 2147483647 13 | fmt.Println(int32(math.Pow(2, 31))) // -2147483648 14 | 15 | // int64 16 | fmt.Println(^int64(math.Pow(2, 63))) // -9223372036854775808 17 | fmt.Println(int64(math.Pow(2, 63))) // 9223372036854775807 18 | 19 | // constants/overflow/main.go:11:13: constant 1267650600228229400000000000000 overflows int 20 | fmt.Println(int(Huge)) 21 | } 22 | -------------------------------------------------------------------------------- /constants/scope/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/gophertuts/go-basics/constants/scope/p1" 6 | ) 7 | 8 | const ( 9 | Exported = 10 10 | unExported = "Hello" 11 | ) 12 | 13 | func main() { 14 | const ( 15 | private = 10 16 | Private = "Hello" 17 | ) 18 | 19 | fmt.Println("main: p1: Exported: ", p1.Exported) 20 | fmt.Println("main: Exported: ", Exported) 21 | fmt.Println("main: unExported: ", unExported) 22 | fmt.Println("main: Private: ", Private) 23 | fmt.Println("main: private: ", private) 24 | } 25 | -------------------------------------------------------------------------------- /constants/scope/p1/p1.go: -------------------------------------------------------------------------------- 1 | package p1 2 | 3 | import ( 4 | "fmt" 5 | "github.com/gophertuts/go-basics/constants/scope/p2" 6 | ) 7 | 8 | const ( 9 | Exported = "exported" 10 | unExported = 10 11 | ) 12 | 13 | func init() { 14 | fmt.Println("p1: unExported:", unExported) 15 | fmt.Println("p1: p2: Exported:", p2.Exported) 16 | } 17 | -------------------------------------------------------------------------------- /constants/scope/p2/p2.go: -------------------------------------------------------------------------------- 1 | package p2 2 | 3 | const Exported = 10 4 | -------------------------------------------------------------------------------- /constants/strings/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | const s = "Hello" 6 | 7 | var bs = []rune{'H', 'e', 'l', 'l', 'o'} 8 | 9 | func main() { 10 | // cannot assign to s[0] 11 | // s[0] = 'M' 12 | fmt.Println(s) 13 | 14 | bs[0] = 'M' 15 | fmt.Println(string(bs)) 16 | } 17 | -------------------------------------------------------------------------------- /constants/types/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | const ( 6 | // typed 7 | b bool = true 8 | i int = -64 - 32 9 | i8 int8 = -8 10 | i16 int16 = -16 11 | i32 int32 = -32 12 | r rune = 'c' // alias of in32 13 | i64 int64 = -64 14 | u uint = 1e2 15 | u8 uint8 = 8 16 | bb byte = 20 // alias of uint8 17 | u16 uint16 = 16 18 | u32 uint32 = 32 19 | u64 uint64 = 64 20 | uptr uintptr = '\u0001' 21 | f32 float32 = 3.2 22 | f64 float64 = 6.4 23 | c64 complex64 = 6 + 4i 24 | c128 complex128 = 12 + 8i 25 | str string = "Hello" 26 | 27 | // untyped 28 | untypedB = false 29 | untypedInt = 10 30 | untypedIntIota = iota // alias of untyped int 31 | untypedRune = '汉' 32 | untypedFloat = 2.0 33 | untypedComplex = 2 + 0i 34 | untypedString = "World" 35 | 36 | // const expressions 37 | exp1 = 4.5 + 1 + 2i 38 | exp2 = 12 + 3.5 39 | exp3 = 'H' + 'e' + 'l' + 'l' + 'o' + ' ' + 'W' + 'o' + 'r' + 'l' + 'd' 40 | exp4 = str + " " + untypedString 41 | ) 42 | 43 | func main() { 44 | fmt.Printf("exp1: Value: %v Type: %T\n", exp1, exp1) 45 | fmt.Printf("exp2: Value: %v Type: %T\n", exp2, exp2) 46 | fmt.Printf("exp3: Value: %v Type: %T\n", exp3, exp3) 47 | fmt.Printf("exp4: Value: %v Type: %T\n", exp4, exp4) 48 | } 49 | -------------------------------------------------------------------------------- /custom-import-path/Custom import path.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/custom-import-path/Custom import path.key -------------------------------------------------------------------------------- /custom-import-path/Custom import path.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/custom-import-path/Custom import path.pdf -------------------------------------------------------------------------------- /custom-import-path/Custom import path.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/custom-import-path/Custom import path.pptx -------------------------------------------------------------------------------- /custom-import-path/README.md: -------------------------------------------------------------------------------- 1 | # Custom **import** path in Go 2 | 3 | ## Overview 4 | 5 | The purpose of this tutorial is to teach you what are custom import 6 | paths in Go and how can you make use of this feature to your advantage. 7 | 8 | In this tutorial you will learn how to set up a custom import path 9 | static Go server, which tells us the client which cloud provider 10 | to use for our import and we'll have a small program 11 | which uses that package. 12 | 13 | The main topics we're gonna cover are: 14 | 15 | - `Custom import paths` 16 | - `Import path checking` 17 | 18 | ## Medium version 📖 19 | 20 | [Custom import paths in Go](https://medium.com/@gophertuts/packages-in-go-df5438123548) 21 | 22 | ### How to run: 23 | 24 | 1. Custom `go get` **import** path 25 | 26 | ```bash 27 | # cd into the example 28 | cd $GOPATH/src/github.com/gophertuts/go-basics/custom-import-path/custom-path 29 | 30 | # fetch the package from custom URL 31 | go get -insecure -u 0.0.0.0/user/pkg 32 | 33 | # spin an HTTP static server 34 | go run server.go 35 | ``` 36 | 37 | #### Run GitLab Docker server: 38 | 39 | ***Disclaimer***: GitLab says it's not guaranteed to work on Windows, 40 | so if you happen to use Windows. You can try this out, but not 41 | sure it's going to reproduce or work properly. 42 | 43 | You can though try it on Linux, i.e. Ubuntu 44 | 45 | ```bash 46 | # run the docker container and expose port 443 and 8000 47 | # don't forget to map the volumes correctly as shown below 48 | # we use port 8000 to not collapse with port 80 which we need by server.go 49 | docker run --detach \ 50 | --hostname gitlab.example.com \ 51 | --publish 443:443 --publish 8000:80 \ 52 | --restart always \ 53 | --volume ~/Desktop/gitlab/config:/etc/gitlab \ 54 | --volume ~/Desktop/gitlab/log:/var/log/gitlab \ 55 | --volume ~/Desktop/gitlab/opt:/var/opt/gitlab \ 56 | gitlab/gitlab-ce:latest 57 | 58 | # display real time logs for GitLab docker container 59 | docker logs --follow [CONTAINER_ID] 60 | 61 | # WAIT TILL IT FINISHES 62 | 63 | # open up localhost:8000 64 | 65 | # set up a new password, preferably something which uses 66 | # Uppercase, letters, numbers, alphanumeric characters 67 | # otherwise GitLab won't allow you to go further 68 | # something like: Pas$word123456 69 | 70 | # login with the credentials: 71 | # username: root 72 | # password: [PASSWORD_YOU_CREATED] 73 | 74 | # create a repository from the admin panel and name it `some-test` 75 | 76 | # clone the created repository on your local machine 77 | git clone http://localhost:8000/root/some-test.git 78 | 79 | # add the go pkg shown bellow and save it inside pkg.go 80 | 81 | git add -A 82 | 83 | git commit -m "initial commit" 84 | 85 | git push 86 | 87 | # input your username: root 88 | # input your password: [PASSWORD_YOU_CREATED] 89 | 90 | # DONE 91 | ``` 92 | 93 | ###### `pkg.go` 94 | ```go 95 | package pkg // import "0.0.0.0/user/pkg" 96 | 97 | import "fmt" 98 | 99 | func New() { 100 | fmt.Println("Welcome to pkg! (GitLab - Docker)") 101 | } 102 | ``` 103 | 104 | #### More info 105 | 106 | ***Note***: import path checking is disabled when using 107 | `Go modules` or `vendor` directory 108 | 109 | ```bash 110 | # displays useful information about import paths in Go 111 | go help importpath 112 | 113 | # displays useful information about Go specific env variables 114 | # i.e. GO111MODULE 115 | go help environment 116 | ``` 117 | 118 | ## Resources 💎 119 | 120 | - [`go get` custom import path](https://jve.linuxwall.info/blog/index.php?post/2015/08/26/Hosting_Go_code_on_Github_with_custom_import_path) 121 | - [Remote import paths](https://golang.org/cmd/go/#hdr-Remote_import_paths) 122 | - [Custom import path checking](https://docs.google.com/document/d/1jVFkZTcYbNLaTxXD9OcGfn7vYv5hWtPx9--lTx1gPMs/edit) 123 | - [GitLab Docker](https://docs.gitlab.com/omnibus/docker/) 124 | 125 | ## FEEDBACK ⚗ 126 | 127 | [GopherTuts TypeForm](http://feedback.gophertuts.com) 128 | 129 | ## COMMUNITY 🙌 130 | 131 | [GopherTuts Discord](https://discord.gg/4sgecdh) 132 | 133 | --- 134 | 135 | Back to 136 | [Go Basics](https://github.com/gophertuts/go-basics) 137 | 138 | 139 | -------------------------------------------------------------------------------- /custom-import-path/custom-path/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "0.0.0.0/user/pkg" 4 | 5 | func main() { 6 | pkg.New() 7 | } 8 | -------------------------------------------------------------------------------- /custom-import-path/custom-path/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | ) 8 | 9 | const html = ` 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | Nothing to see here; move along. 18 | 19 | ` 20 | 21 | var projects = map[string]struct { 22 | vcs string 23 | remoteURL string 24 | }{ 25 | "github": { 26 | vcs: "git", 27 | remoteURL: "https://github.com/steevehook/some-test", 28 | }, 29 | "gitlab": { 30 | vcs: "git", 31 | remoteURL: "https://gitlab.com/steevehook/some-test", 32 | }, 33 | "gitlab-docker": { 34 | vcs: "git", 35 | remoteURL: "http://localhost:8000/root/some-test.git", 36 | }, 37 | "bitbucket-git": { 38 | vcs: "git", 39 | remoteURL: "https://bitbucket.org/steevehook/some-test-git", 40 | }, 41 | // BitBucket says they will stop Mercurial support by Feb 2020. Be aware 42 | "bitbucket-hg": { 43 | vcs: "hg", 44 | remoteURL: "https://bitbucket.org/steevehook/some-test-hg", 45 | }, 46 | } 47 | 48 | func main() { 49 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 50 | tpl := fmt.Sprintf(html, projects["github"].vcs, projects["gitlhub"].remoteURL) 51 | fmt.Fprint(w, tpl) 52 | }) 53 | log.Fatal(http.ListenAndServe(":80", nil)) 54 | } 55 | -------------------------------------------------------------------------------- /custom-import-path/import-path-checking/README.md: -------------------------------------------------------------------------------- 1 | # Import path checking 2 | 3 | ## Overview 4 | 5 | This program proves how `import path checking` works 6 | when enabled from a certain package. 7 | 8 | ***Note***: this is a feature designed mainly for 9 | custom import paths which use `custom domains (hosts)` 10 | instead of fixed hosting services 11 | such as `GitHub`, `BitBucket`, `GitLab` and others. 12 | 13 | ```bash 14 | # NOT GOING TO WORK (COMPILE) 15 | # but the package will be downloaded inside 16 | # $GOPATH/src/github.com/steevehook/some-test 17 | go get github.com/steevehook/some-test 18 | 19 | # Will fail, because of wrong import path 20 | go run main.go 21 | ``` 22 | -------------------------------------------------------------------------------- /custom-import-path/import-path-checking/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/steevehook/some-test/pkg" 4 | 5 | func main() { 6 | // this won't even compile 7 | // because of import path checking 8 | pkg.New() 9 | } 10 | -------------------------------------------------------------------------------- /custom-package-manager/Custom package manger.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/custom-package-manager/Custom package manger.key -------------------------------------------------------------------------------- /custom-package-manager/README.md: -------------------------------------------------------------------------------- 1 | # Custom package manager 2 | 3 | ## Medium version 📖 4 | 5 | [Custom package manager in Go](https://medium.com/@gophertuts/packages-in-go-df5438123548) 6 | 7 | #### How to test 8 | 9 | ```bash 10 | # generate pkg-manager binary and places it inside $GOPATH/bin 11 | go install 12 | 13 | # export $GOPATH/bin and add it inside $PATH env variable 14 | echo "export GOBIN=$GOPATH/bin\nexport PATH=$GOBIN:$PATH" >> .bashrc 15 | echo "export GOBIN=$GOPATH/bin\nexport PATH=$GOBIN:$PATH" >> .zshrc 16 | 17 | # create a simple go project 18 | mkdir project-name 19 | touch go-pkg.json 20 | # or using 21 | pkg-manager init project-name 22 | 23 | # downloads all dependencies indicated in go-pkg.json 24 | pkg-manager get ./... 25 | 26 | # downloads the specified dependency and saves it inside in go-pkg.json 27 | # using either the version tag in format: 'v1.2.3' 28 | # or using the commit hash 29 | pkg-manager get github.com/user/repo@version 30 | pkg-manager get github.com/user/repo@GIT_COMMIT_HASH 31 | ``` 32 | 33 | #### Useful info 34 | 35 | ```bash 36 | go help importpath 37 | ``` 38 | 39 | #### Improvements 40 | 41 | - Add recursive dependency tree fetching 42 | - Add a lock file with detailed dependency tree 43 | - Add a caching mechanism and/or proxy mechanism 44 | - Implement Go's download protocol 45 | - Don't save git repositories, just the actual code 46 | - Add support for archives instead of VCS checkouts 47 | - Add the possibility to skip test files or non go files to save bandwidth 48 | - Add support for custom domains & custom import paths 49 | - Add support for multiple VCS systems 50 | 51 | ## Resources 💎 52 | 53 | - [Go 1.5 vendor experiment](https://go.googlesource.com/proposal/+/master/design/25719-go15vendor.md) 54 | - [Vendor directories](https://golang.org/cmd/go/#hdr-Vendor_Directories) 55 | - [VGO module](https://research.swtch.com/vgo-module) 56 | - [Go project structure](https://vsupalov.com/go-folder-structure/) 57 | - [Go project layout](https://github.com/golang-standards/project-layout) 58 | - [Dep package manager](https://github.com/golang/dep) 59 | - [Project Athens - the download protocol](https://medium.com/@arschles/project-athens-the-download-protocol-2b346926a818) 60 | - [Go module proxy protocol](https://golang.org/cmd/go/#hdr-Module_proxy_protocol) 61 | - [Go module proxy - Fatih Arslan](https://arslan.io/2019/08/02/why-you-should-use-a-go-module-proxy/) 62 | - [Go proxies](https://roberto.selbach.ca/go-proxies/) 63 | - [Athens - GitHub project](https://medium.com/@arschles/project-athens-the-download-protocol-2b346926a818) 64 | - [Go module sum](https://sum.golang.org/) 65 | 66 | ## FEEDBACK ⚗ 67 | 68 | [GopherTuts TypeForm](http://feedback.gophertuts.com) 69 | 70 | ## COMMUNITY 🙌 71 | 72 | [GopherTuts Discord](https://discord.gg/4sgecdh) 73 | 74 | --- 75 | 76 | Back to 77 | [Go Basics](https://github.com/gophertuts/go-basics) 78 | 79 | -------------------------------------------------------------------------------- /custom-package-manager/pkg-manager/downloader.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "os" 6 | "path" 7 | "strings" 8 | 9 | "gopkg.in/src-d/go-git.v4" 10 | "gopkg.in/src-d/go-git.v4/plumbing" 11 | ) 12 | 13 | const vendor = "vendor" 14 | 15 | func Download(deps map[string]string) { 16 | for dependency, version := range deps { 17 | _, err := os.Stat(vendor) 18 | if os.IsNotExist(err) { 19 | createVendor(dependency) 20 | } else { 21 | deleteVendor(dependency) 22 | createVendor(dependency) 23 | } 24 | repo, err := git.PlainClone( 25 | path.Join(".", vendor, dependency), 26 | false, &git.CloneOptions{ 27 | URL: "https://" + dependency, 28 | Progress: os.Stdout, 29 | }) 30 | if err != nil { 31 | log.Fatalf("%+v: %s", err, dependency) 32 | } 33 | checkout(repo, version) 34 | } 35 | } 36 | 37 | func createVendor(dependency string) { 38 | err := os.MkdirAll( 39 | path.Join(".", vendor, dependency), 40 | 0755, 41 | ) 42 | if err != nil { 43 | log.Fatal(err) 44 | } 45 | } 46 | 47 | func deleteVendor(dependency string) { 48 | err := os.RemoveAll(path.Join(".", vendor, dependency)) 49 | if err != nil { 50 | log.Fatal(err) 51 | } 52 | } 53 | 54 | func versionToHash(repo *git.Repository, version string) string { 55 | if version == "master" { 56 | head, _ := repo.Head() 57 | return head.String() 58 | } 59 | tags, _ := repo.Tags() 60 | for { 61 | tag, err := tags.Next() 62 | if err != nil { 63 | break 64 | } 65 | if strings.Contains(tag.Name().String(), version) { 66 | return tag.Hash().String() 67 | } 68 | } 69 | commits, _ := repo.CommitObjects() 70 | for { 71 | commit, err := commits.Next() 72 | if err != nil { 73 | break 74 | } 75 | if strings.Contains(commit.Hash.String(), version) { 76 | return commit.Hash.String() 77 | } 78 | } 79 | return "" 80 | } 81 | 82 | func checkout(repo *git.Repository, version string) { 83 | workTree, err := repo.Worktree() 84 | if err != nil { 85 | log.Fatal(err) 86 | } 87 | hash := versionToHash(repo, version) 88 | if hash == "" { 89 | cfg, _ := repo.Config() 90 | log.Fatalf( 91 | "no such version: '%s' for origin remote: '%s'", 92 | version, 93 | cfg.Remotes["origin"].URLs[0], 94 | ) 95 | } 96 | if err = workTree.Checkout(&git.CheckoutOptions{ 97 | Hash: plumbing.NewHash(versionToHash(repo, version)), 98 | }); err != nil { 99 | log.Fatal(err) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /custom-package-manager/pkg-manager/go-pkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "github.com/julienschmidt/httprouter": "v1.3.0", 4 | "github.com/sirupsen/logrus": "v1.4.2", 5 | "github.com/stretchr/testify": "f35b8ab", 6 | "github.com/uber-go/zap": "master" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /custom-package-manager/pkg-manager/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | "strings" 8 | ) 9 | 10 | func main() { 11 | args := os.Args[1:] 12 | helpMsg := "\nUSAGE:" + 13 | "\npkg-manager help\t\t\t\t\t\t\t\t --- " + 14 | "displays this message\n" + 15 | "\npkg-manager init project-name\t\t\t\t\t\t\t --- " + 16 | "creates a new bare bones project\n" + 17 | "\npkg-manager get ./...\t\t\t\t\t\t\t\t --- " + 18 | "downloads all dependencies specified in 'go-pkg.json'\n" + 19 | "\npkg-manager get github.com/user1/repo@version github.com/user2/repo@version\t --- " + 20 | "downloads the mentioned list of dependencies using the git tag version and updates the go-pkg.json\n" + 21 | "\npkg-manager get github.com/user/repo@GIT_COMMIT_HASH\n" + 22 | "\npkg-manager get github.com/user/repo@GIT_COMMIT_HASH\t\t\t\t --- " + 23 | "downloads the mentioned list of dependencies using the git commit hash and updates the go-pkg.json\n" 24 | if len(args) > 0 && args[0] == "help" { 25 | fmt.Print(helpMsg) 26 | return 27 | } 28 | 29 | if len(args) < 2 { 30 | helpMsg = "Incorrect use of command\n" + helpMsg 31 | log.Fatal(helpMsg) 32 | } 33 | 34 | cmd := strings.TrimSpace(strings.ToLower(args[0])) 35 | cmdArgs := args[1:] 36 | m := NewManager([2]string{args[0], args[1]}) 37 | 38 | switch { 39 | case cmd == "init" && len(cmdArgs) == 1: 40 | fmt.Println("=== creating a bare bones project ===") 41 | CreateProject(cmdArgs[0]) 42 | UpdateGoPkg(m, map[string]string{}) 43 | case cmd == "get" && cmdArgs[0] == "./...": 44 | fmt.Println("=== downloading all dependencies from go-pkg.json ===") 45 | Download(m.Dependencies) 46 | case cmd == "get" && cmdArgs[0] != "./...": 47 | deps := NewDependencies(cmdArgs) 48 | fmt.Println("=== downloading specified dependencies ===") 49 | Download(deps) 50 | fmt.Println("=== updating go-pkg.json ===") 51 | UpdateGoPkg(m, deps) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /custom-package-manager/pkg-manager/manager.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "fmt" 7 | "io/ioutil" 8 | "log" 9 | "os" 10 | "path" 11 | "strings" 12 | ) 13 | 14 | type Manager struct { 15 | WorkDir string `json:"-"` 16 | Dependencies map[string]string `json:"dependencies"` 17 | } 18 | 19 | func NewManager(args [2]string) Manager { 20 | if strings.TrimSpace(strings.ToLower(args[0])) == "init" { 21 | return Manager{ 22 | WorkDir: args[1], 23 | Dependencies: map[string]string{}, 24 | } 25 | } 26 | var m Manager 27 | err := json.Unmarshal(readGoPkg(), &m) 28 | if err != nil { 29 | log.Fatal(err) 30 | } 31 | return m 32 | } 33 | 34 | func NewDependencies(packageList []string) map[string]string { 35 | deps := map[string]string{} 36 | for _, dep := range packageList { 37 | ds := strings.Split(dep, "@") 38 | pkg := ds[0] 39 | var version string 40 | if len(ds) < 2 { 41 | version = "master" 42 | } else { 43 | version = ds[1] 44 | } 45 | deps[pkg] = version 46 | } 47 | return deps 48 | } 49 | 50 | func CreateProject(projectName string) { 51 | fmt.Println("=== creating project directory ===") 52 | err := os.Mkdir(path.Join(".", projectName), 0755) 53 | if err != nil { 54 | log.Fatalf("could not create project directory\n%+v", err) 55 | } 56 | fmt.Println("=== creating empty go-pkg.json file ===") 57 | _, err = os.Create(path.Join(".", projectName, "go-pkg.json")) 58 | if err != nil { 59 | log.Fatalf("could not create go-pkg.json file\n%+v", err) 60 | } 61 | } 62 | 63 | func UpdateGoPkg(m Manager, newDeps map[string]string) { 64 | for dep, ver := range newDeps { 65 | m.Dependencies[dep] = ver 66 | } 67 | // JSON marshall the manager 68 | bs, _ := json.Marshal(m) 69 | bs = append(bs, '\n') 70 | 71 | // write the new result to the file 72 | err := ioutil.WriteFile(path.Join(".", m.WorkDir, "go-pkg.json"), prettyPrint(bs), 0755) 73 | if err != nil { 74 | log.Fatal(err) 75 | } 76 | } 77 | 78 | func readGoPkg() []byte { 79 | file, err := os.Open("go-pkg.json") 80 | if err != nil { 81 | log.Fatalf("go-pkg.json not found, create one\n%+v", err) 82 | } 83 | bs, _ := ioutil.ReadAll(file) 84 | return bs 85 | } 86 | 87 | func prettyPrint(b []byte) []byte { 88 | var out bytes.Buffer 89 | _ = json.Indent(&out, b, "", " ") 90 | return out.Bytes() 91 | } 92 | -------------------------------------------------------------------------------- /go-commands.md: -------------------------------------------------------------------------------- 1 | # Go useful commands explained 2 | 3 | Here are a list of *daily Go commands* used by developers, which will 4 | help you stay productive if you know about them. 5 | 6 | ## Frequently used commands 7 | 8 | ### `go get` 9 | 10 | Downloads *third party packages*, by *git* cloning the repository 11 | and installing binaries if any 12 | 13 | Example: 14 | ```bash 15 | # downloads the "errors" package 16 | go get github.com/pkg/errors 17 | 18 | # downloads and updates the "errors" package 19 | go get -u github.com/pkg/errors 20 | 21 | # downloads all packages that the current project imports/uses 22 | go get ./... 23 | ``` 24 | 25 | ### `go run` 26 | 27 | Compiles and builds the project, after which it generates a binary in 28 | a temporary location then executes that binary 29 | 30 | Example: 31 | ```bash 32 | # Compiles "main.go" and executes the binary 33 | go run main.go 34 | 35 | # Compiles "main.go" and "package.go" and executes the binary 36 | go run main.go package.go 37 | 38 | # Compiles all ".go" files in CWD and executes the binary 39 | go run *.go 40 | ``` 41 | 42 | ### `go build` 43 | 44 | Compiles and creates executable binary from source code 45 | 46 | Example: 47 | ```bash 48 | go build 49 | 50 | go build -o executable-name 51 | ``` 52 | 53 | ### `go test` 54 | 55 | Runs all Go tests which are located inside *_test.go* files from 56 | current working directory 57 | 58 | Example: 59 | ```bash 60 | go test ./... 61 | ``` 62 | 63 | ## Other useful commands 64 | 65 | ### `go install` 66 | 67 | Compiles Go code from binary.go and creates a binary called 68 | "bin" then places it inside `$GOPATH/bin` directory 69 | 70 | In order for this to work the file need to in **package main** 71 | and have a **main** function 72 | 73 | Example: 74 | ```bash 75 | go install bin.go 76 | ``` 77 | 78 | ### `go fmt` 79 | 80 | Formats all Go code from current working directory 81 | 82 | Example: 83 | ```bash 84 | go fmt ./... 85 | ``` 86 | 87 | ### `go vet` 88 | 89 | Checks for potential Go issues in current working directory 90 | 91 | Example: 92 | ```bash 93 | go vet ./... 94 | ``` 95 | 96 | ### `go env` 97 | 98 | Displays all environment variables that Go uses and their values 99 | 100 | ### `go help` 101 | 102 | Displays a list of all available *Go commands*. Have fun and play 103 | around with them 104 | 105 | For more info about Go commands check out 106 | [Go Commands](https://golang.org/cmd/go/) 107 | 108 | Back to 109 | [Go Basics](https://github.com/gophertuts/go-basics) 110 | -------------------------------------------------------------------------------- /go-environment-variables/README.md: -------------------------------------------------------------------------------- 1 | # Environment variables in Go 2 | -------------------------------------------------------------------------------- /go-learning-resources/Go Resources.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/go-learning-resources/Go Resources.key -------------------------------------------------------------------------------- /go-learning-resources/Go Resources.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/go-learning-resources/Go Resources.pdf -------------------------------------------------------------------------------- /go-learning-resources/Go Resources.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/go-learning-resources/Go Resources.pptx -------------------------------------------------------------------------------- /go-learning-resources/README.md: -------------------------------------------------------------------------------- 1 | # Go Resources 2 | 3 | ## Blog posts & Docs 4 | 5 | A good place for reading articles, blog posts & practicing Go by example 6 | The place that really takes you from zero to hero in no time 7 | I highly recommend checking these first, they will tremendously 8 | boost your development and save you a lot of time 9 | 10 | - [GoTour](https://tour.golang.org/welcome/1) 11 | - [Effective Go](https://golang.org/doc/effective_go.html) 12 | - [Go Blog](https://blog.golang.org/) 13 | - [Go Doc](https://godoc.org/) 14 | - [Golang Spec](https://golang.org/) 15 | - [Go by Example](https://gobyexample.com/) 16 | - [Go Proverbs](https://go-proverbs.github.io/) 17 | - [Awesome Go](https://github.com/avelino/awesome-go) 18 | - [Idiomatic Go](https://dmitri.shuralyov.com/idiomatic-go) 19 | - [Idiomatic Go - Sourcegraph](https://about.sourcegraph.com/go/idiomatic-go) 20 | - [Dave Cheney](https://dave.cheney.net/) 21 | - [Medium Golang](https://medium.com/search?q=golang) 22 | 23 | ## Discussions & Q&A 24 | 25 | A good place to keep in touch with the community. Talk & share 26 | different solutions or help others solve their difficulties 27 | 28 | - [Golang Redit](https://www.reddit.com/r/golang) 29 | - [Go Forum](https://forum.golangbridge.org/) 30 | 31 | ## Twitter influencers 32 | 33 | Having mentors is insanely important and can drive the wheel so much 34 | faster in software engineering. Make sure to follow the best of the 35 | best in the community and keep up with the latest news 36 | 37 | - [@davecheney](https://twitter.com/@davecheney) 38 | - [@rob_pike](https://twitter.com/@rob_pike) 39 | - [@_rsc](https://twitter.com/@_rsc) 40 | - [@cool_golang](https://twitter.com/@cool_golang) 41 | - [@Cassandraoid](https://twitter.com/@Cassandraoid) 42 | - [@GopherCon](https://twitter.com/@GopherCon) 43 | - [@welovegolang](https://twitter.com/@welovegolang) 44 | - [@golangprojects](https://twitter.com/@golangprojects) 45 | - [@GopherAcademy](https://twitter.com/@GopherAcademy) 46 | - [@golangweekly](https://twitter.com/@golangweekly) 47 | - [@martinfowler](https://twitter.com/@martinfowler) 48 | - [@RealGophersShip](https://twitter.com/@RealGophersShip) 49 | - [@GopherTuts](https://twitter.com/@GopherTuts) 50 | - [@francesc](https://twitter.com/@francesc) 51 | - [@Todd_McLeod](https://twitter.com/@Todd_McLeod) 52 | 53 | ## Books 54 | 55 | These are books which I've read, reading at the moment or books which 56 | are the best known in the community. There's no better explanation than 57 | one in a book. Grab some coffee and read some cool Go books ☕☕☕ 58 | 59 | - [The Go Programming Language](https://www.amazon.com/Programming-Language-Addison-Wesley-Professional-Computing/dp/0134190440) 60 | - [The way to Go](https://archive.org/details/TheWayToGo) 61 | - [Go in Action](https://www.amazon.com/Go-Action-William-Kennedy/dp/1617291781) 62 | - [Go in Practice](https://www.amazon.com/gp/product/1633430073/ref=x_gr_w_bb?ie=UTF8&tag=x_gr_w_bb-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=1633430073&SubscriptionId=1MGPYB6YW3HWK55XCGG2) 63 | - [Other Books](https://github.com/golang/go/wiki/Books) 64 | 65 | ## YouTube channels 66 | 67 | For people who like learning visually and preferably free good video 68 | tutorials seems like an impossible task to accomplish. YouTube is 69 | so full of videos and until you find something good, it takes time 70 | or you simply don't find. 71 | 72 | Here are a list of channels I consider are the best for learning Go 73 | and I myself have subscribed to: 74 | 75 | - [JustForFunc](https://www.youtube.com/channel/UC_BzFbxG2za3bp5NRRRXJSw) 76 | - [Gopher Academy](https://www.youtube.com/channel/UCx9QVEApa5BKLw9r8cnOFEA/feed) 77 | - [GopherCon UK](https://www.youtube.com/channel/UC9ZNrGdT2aAdrNbX78lbNlQ) 78 | - [Coding Tech](https://www.youtube.com/channel/UCtxCXg-UvSnTKPOzLH4wJaQ) 79 | - [The Go Programming language](https://www.youtube.com/user/gocoding) 80 | - [GOTO Conferences](https://www.youtube.com/user/GotoConferences) 81 | - [Russ Cox](https://www.youtube.com/user/rscgolang) 82 | - [Learn to Code - Todd McCleod](https://www.youtube.com/user/toddmcleod) 83 | 84 | ## Udemy courses 85 | 86 | YouTube or other similar free video services can be overwhelming 87 | and cluttered many times. You don't just find good free videos, that's 88 | why the best videos are those organized inside courses 89 | 90 | Of course paid courses, but let's be serious this is like the cheapest 91 | platform where you get lifetime access to courses and updates 92 | 93 | These are the courses I've finished when I first started to learn Go 94 | and recommend doing if you're like me and like learning from 95 | videos 96 | 97 | - [Learn How To Code: Google's Go (golang) Programming Language - T. McCleod](https://www.udemy.com/course/learn-how-to-code/) 98 | - [Web Development w/ Google’s Go (golang) Programming Language - T. McCleod](https://www.udemy.com/course/go-programming-language/) 99 | - [Go: The Complete Developer's Guide (Golang) - Stephen Grider](https://www.udemy.com/course/go-the-complete-developers-guide/) 100 | 101 | ## GitHub 102 | 103 | GitHub is the place where Open Source is. It's also the place where 104 | are the latest changes, nothing is more actual the master branch 105 | 106 | Wanna be in touch with what's happening in the Go world, have a 107 | look at these repositories full of examples and best practices on 108 | writing idiomatic Go code 109 | 110 | - [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments) 111 | - [Awesome Go](https://github.com/avelino/awesome-go) 112 | - [Go Books](https://github.com/golang/go/wiki/Books) 113 | - [Go Training Ardan Labs](https://github.com/ardanlabs/gotraining) 114 | - [Go Training Todd McCleod](https://github.com/GoesToEleven/GolangTraining) 115 | - [Go Web Dev](https://github.com/GoesToEleven/golang-web-dev) 116 | - [Go GH Organization](https://github.com/golang) 117 | 118 | ## Mail subscriptions 119 | 120 | The best way to be up to date is by letting someone notify you 121 | We all use mail boxes, so that the best way to stay tuned and keep in 122 | touch with the latest trends in Go 123 | 124 | Be careful and stay away from spamming your Inbox 125 | 126 | - [Golang Weekly](https://golangweekly.com/) 127 | - [Awesome Go](https://go.libhunt.com/newsletter) 128 | - [Jon Calhoun](https://www.calhoun.io/) 129 | 130 | Hope this was useful. Now go ahead and use this knowledge! 🚀🚀🚀 131 | 132 | ## FEEDBACK ⚗ 133 | 134 | [GopherTuts TypeForm](https://gophertuts.typeform.com/to/j2CJmC) 135 | 136 | ## COMMUNITY 🙌 137 | 138 | [GopherTuts Discord](https://discord.gg/4sgecdh) 139 | 140 | --- 141 | 142 | Back to 143 | [Go Basics](https://github.com/gophertuts/go-basics) 144 | 145 | 146 | -------------------------------------------------------------------------------- /go-module-proxy/Go module proxy.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/go-module-proxy/Go module proxy.key -------------------------------------------------------------------------------- /go-module-proxy/README.md: -------------------------------------------------------------------------------- 1 | # Go module proxy 2 | 3 | 4 | ## Medium version 📖 5 | 6 | [Go module proxy](https://medium.com/@gophertuts/packages-in-go-df5438123548) 7 | 8 | ### More info 9 | 10 | ```bash 11 | go help importpath 12 | 13 | go help goproxy 14 | ``` 15 | 16 | ## Resources 💎 17 | 18 | - [Go 1.5 vendor experiment](https://go.googlesource.com/proposal/+/master/design/25719-go15vendor.md) 19 | - [Vendor directories](https://golang.org/cmd/go/#hdr-Vendor_Directories) 20 | - [VGO module](https://research.swtch.com/vgo-module) 21 | - [Athens project](https://docs.gomods.io) 22 | - [Athens project - GitHub](https://github.com/gomods/athens) 23 | - [Athens docker image](https://docs.gomods.io) 24 | - [Go project structure](https://vsupalov.com/go-folder-structure/) 25 | - [Go project layout](https://github.com/golang-standards/project-layout) 26 | 27 | ## FEEDBACK ⚗ 28 | 29 | [GopherTuts TypeForm](http://feedback.gophertuts.com) 30 | 31 | ## COMMUNITY 🙌 32 | 33 | [GopherTuts Discord](https://discord.gg/4sgecdh) 34 | 35 | --- 36 | 37 | Back to 38 | [Go Basics](https://github.com/gophertuts/go-basics) 39 | 40 | 41 | -------------------------------------------------------------------------------- /go-modules/@latest/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /go-modules/Go modules.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/go-modules/Go modules.key -------------------------------------------------------------------------------- /go-modules/README.md: -------------------------------------------------------------------------------- 1 | # Go Modules 2 | 3 | ### `$GOPATH` 4 | 5 | ```bash 6 | # display useful information about $GOPATH 7 | go help gopath 8 | ``` 9 | 10 | ### `$GOPRIVATE` 11 | 12 | ```bash 13 | # Lists all available packages inside $GOPATH 14 | # OR All packages inside current module 15 | # if env variable GO111MODULE=on 16 | go list all 17 | 18 | # Lists all std lib packages and its sub packages 19 | # Works the same as `go list all` 20 | go list std 21 | 22 | # Lists all cmd packages and its sub packages 23 | # Works the same as `go list all` 24 | go list cmd 25 | 26 | # Lists all available local packages in CWD 27 | go list ./... 28 | 29 | # Lists all imported (local) packages in a JSON format 30 | go list -json ./... 31 | 32 | # Displays useful information about import paths 33 | go help importpath 34 | ``` 35 | 36 | ## Resources 💎 37 | 38 | - [Migrating to Go modules](https://blog.golang.org/migrating-to-go-modules) 39 | - [VGO module](https://research.swtch.com/vgo-module) 40 | - [Module configuration (private modules)](https://golang.org/cmd/go/#hdr-Module_configuration_for_non_public_modules) 41 | 42 | ## FEEDBACK ⚗ 43 | 44 | [GopherTuts TypeForm](http://feedback.gophertuts.com) 45 | 46 | ## COMMUNITY 🙌 47 | 48 | [GopherTuts Discord](https://discord.gg/4sgecdh) 49 | 50 | --- 51 | 52 | Back to 53 | [Go Basics](https://github.com/gophertuts/go-basics) 54 | 55 | 56 | -------------------------------------------------------------------------------- /go-modules/basic-http/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /go-modules/download/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /go-modules/go-mod-tidy/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /go-modules/go111module/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /go-modules/incompatible-pkg-versions/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /go-modules/migration-from-dep/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /go-modules/outside-gopath/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /go-modules/vendor-directory/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /go-program-anatomy/Go program anatomy.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/go-program-anatomy/Go program anatomy.key -------------------------------------------------------------------------------- /go-program-anatomy/Go program anatomy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/go-program-anatomy/Go program anatomy.pdf -------------------------------------------------------------------------------- /go-program-anatomy/Go program anatomy.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/go-program-anatomy/Go program anatomy.pptx -------------------------------------------------------------------------------- /go-program-anatomy/README.md: -------------------------------------------------------------------------------- 1 | # Go program anatomy: 2 | 3 | ## Prerequisites 4 | 5 | - Install Docker for your platform by checking 6 | [Docker Installation](https://docs.docker.com/install/) 7 | 8 | ## How to test `go-build` 9 | 10 | Create a Docker container to simulate the Linux environment 11 | FYI: It's easier to run it inside Docker then spinning up a VM ;) 12 | 13 | ```bash 14 | # download the repository with src code if you haven't already 15 | go get github.com/gophertuts/go-basics 16 | 17 | # cd into go-build directory on your machine 18 | cd $GOPATH/src/github.com/gophertuts/go-basics/go-program-anatomy/go-build 19 | ``` 20 | 21 | ```bash 22 | # generate the binary 23 | go build 24 | ``` 25 | 26 | ```bash 27 | # spin up a docker container that simulates linux OS with Go runtime support 28 | docker run --rm -it -v $(pwd):/go/src/github.com/gophertuts/go-basics/go-program-anatomy/go-build golang 29 | ``` 30 | 31 | ```bash 32 | # cd into $GOPATH and run the generated binary 33 | cd /go/src/github.com/gophertuts/go-basics/go-program-anatomy/go-build 34 | ./go-build 35 | ``` 36 | 37 | ## How to test `runtime-vs-buildtime` 38 | 39 | ```bash 40 | # cd into go-build directory on your machine 41 | cd $GOPATH/src/github.com/gophertuts/go-basics/go-program-anatomy/runtime-vs-buildtime 42 | ``` 43 | 44 | ```bash 45 | # generate the binary 46 | env GOOS=linux GOARCH=386 GOHOSTOS=linux GOHOSTARCH=386 \ 47 | go build -ldflags \ 48 | "-X main.hostOS=$(go env GOHOSTOS) -X main.hostArch=$(go env GOHOSTARCH)" 49 | ``` 50 | 51 | ```bash 52 | # spin up a docker container that simulates linux OS with Go runtime support 53 | docker run --rm -it -v $(pwd):/go/src/github.com/gophertuts/go-basics/go-program-anatomy/runtime-vs-buildtime golang 54 | ``` 55 | 56 | ```bash 57 | # cd into $GOPATH and run the generated binary 58 | cd /go/src/github.com/gophertuts/go-basics/go-program-anatomy/runtime-vs-buildtime 59 | ./runtime-vs-buildtime 60 | ``` 61 | 62 | #### Note: 63 | 64 | `$GOOS` and `$GOARCH` are evaluated at compile time and saved as constants 65 | inside `runtime.GOOS` and `runtime.GOARCH` 66 | 67 | Also keep in mind that if `$GOOS` and `$GOARCH` are not set, the 68 | default values will be taken from `$GOHOSTOS` and `$GOHOSTARCH` 69 | which by the way `CANNOT` be changed at `compile/build time` 70 | 71 | 72 | Play around with different `GOOS` & `GOARCH` values, here are some examples: 73 | 74 | - `env GOOS=linux GOARCH=386 go build` 75 | - `env GOOS=linux GOARCH=amd64 go build` 76 | - `env GOOS=darwin GOARCH=386 go build` 77 | - `env GOOS=darwin GOARCH=amd64 go build` 78 | 79 | ## Resources 💎 80 | 81 | - [Go Build](https://golang.org/pkg/go/go-build/) 82 | - [Go supported OS & Architectures](https://gist.github.com/asukakenji/f15ba7e588ac42795f421b48b8aede63) 83 | - [Go source code](https://golang.org/src/) 84 | 85 | ## FEEDBACK ⚗ 86 | 87 | [GopherTuts TypeForm](https://gophertuts.typeform.com/to/j2CJmC) 88 | 89 | ## COMMUNITY 🙌 90 | 91 | [GopherTuts Discord](https://discord.gg/4sgecdh) 92 | 93 | --- 94 | 95 | Back to 96 | [Go Basics](https://github.com/gophertuts/go-basics) 97 | 98 | -------------------------------------------------------------------------------- /go-program-anatomy/go-build/bip_darwin_386.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func bip() { 6 | fmt.Println("Bip from Darwin 32 bit") 7 | } 8 | -------------------------------------------------------------------------------- /go-program-anatomy/go-build/bip_darwin_amd64.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func bip() { 6 | fmt.Println("Bip from Darwin 64 bit") 7 | } 8 | -------------------------------------------------------------------------------- /go-program-anatomy/go-build/bip_linux_386.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func bip() { 6 | fmt.Println("Bip from Linux 32 bit") 7 | } 8 | -------------------------------------------------------------------------------- /go-program-anatomy/go-build/bip_linux_amd64.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func bip() { 6 | fmt.Println("Bip from Linux 64 bit") 7 | } 8 | -------------------------------------------------------------------------------- /go-program-anatomy/go-build/good-bye-darwin-386.go: -------------------------------------------------------------------------------- 1 | // +build darwin,386 2 | 3 | package main 4 | 5 | import "fmt" 6 | 7 | func goodBye() { 8 | fmt.Println("Good bye from Darwin 32 bit") 9 | } 10 | -------------------------------------------------------------------------------- /go-program-anatomy/go-build/good-bye-darwin-amd64.go: -------------------------------------------------------------------------------- 1 | // +build darwin,amd64 2 | 3 | package main 4 | 5 | import "fmt" 6 | 7 | func goodBye() { 8 | fmt.Println("Good bye from Darwin 64 bit") 9 | } 10 | -------------------------------------------------------------------------------- /go-program-anatomy/go-build/good-bye-linux-386.go: -------------------------------------------------------------------------------- 1 | // +build linux,386 2 | 3 | package main 4 | 5 | import "fmt" 6 | 7 | func goodBye() { 8 | fmt.Println("Good bye from Linux 32 bit") 9 | } 10 | -------------------------------------------------------------------------------- /go-program-anatomy/go-build/good-bye-linux-amd64.go: -------------------------------------------------------------------------------- 1 | // +build linux,amd64 2 | 3 | package main 4 | 5 | import "fmt" 6 | 7 | func goodBye() { 8 | fmt.Println("Good bye from Linux 64 bit") 9 | } 10 | -------------------------------------------------------------------------------- /go-program-anatomy/go-build/greet_darwin.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func greet() { 6 | fmt.Println("Greetings from OSX") 7 | } 8 | -------------------------------------------------------------------------------- /go-program-anatomy/go-build/greet_linux.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func greet() { 6 | fmt.Println("Greetings from Linux") 7 | } 8 | -------------------------------------------------------------------------------- /go-program-anatomy/go-build/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | hello() 5 | greet() 6 | bip() 7 | goodBye() 8 | } 9 | -------------------------------------------------------------------------------- /go-program-anatomy/go-build/welcome-linux.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | package main 4 | 5 | import "fmt" 6 | 7 | func hello() { 8 | fmt.Println("Welcome to Linux") 9 | } 10 | -------------------------------------------------------------------------------- /go-program-anatomy/go-build/welcome-osx.go: -------------------------------------------------------------------------------- 1 | // +build darwin 2 | 3 | package main 4 | 5 | import "fmt" 6 | 7 | func hello() { 8 | fmt.Println("Welcome to OSX") 9 | } 10 | -------------------------------------------------------------------------------- /go-program-anatomy/program-flow/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | _ "github.com/gophertuts/go-basics/go-program-anatomy/program-flow/pkg1" 7 | ) 8 | 9 | const ( 10 | mc = "const" 11 | ) 12 | 13 | var ( 14 | mv = mc + ":var" 15 | ) 16 | 17 | func init() { 18 | mv += ":init" 19 | } 20 | 21 | func main() { 22 | mv += ":main" 23 | fmt.Println("package main: mv:", mv) 24 | } 25 | -------------------------------------------------------------------------------- /go-program-anatomy/program-flow/pkg1/pkg1.go: -------------------------------------------------------------------------------- 1 | package pkg1 2 | 3 | import ( 4 | "fmt" 5 | 6 | // pkg2 side effects (init) 7 | _ "github.com/gophertuts/go-basics/go-program-anatomy/program-flow/pkg2" 8 | ) 9 | 10 | const ( 11 | c1 = 1 12 | // other consts 13 | ) 14 | 15 | var ( 16 | v1 = c1 17 | // other vars 18 | ) 19 | 20 | func init() { 21 | fmt.Println("package pkg1: v1:", v1) 22 | } 23 | -------------------------------------------------------------------------------- /go-program-anatomy/program-flow/pkg2/pkg2.go: -------------------------------------------------------------------------------- 1 | package pkg2 2 | 3 | import ( 4 | "fmt" 5 | 6 | // pkg3 side effects (init) 7 | _ "github.com/gophertuts/go-basics/go-program-anatomy/program-flow/pkg3" 8 | ) 9 | 10 | const ( 11 | c2 = 10 12 | // other consts 13 | ) 14 | 15 | var ( 16 | v2 = c2 17 | // other vars 18 | ) 19 | 20 | func init() { 21 | fmt.Println("package pkg2: v2:", v2) 22 | } 23 | -------------------------------------------------------------------------------- /go-program-anatomy/program-flow/pkg3/pkg3.go: -------------------------------------------------------------------------------- 1 | package pkg3 2 | 3 | import "fmt" 4 | 5 | func init() { 6 | fmt.Println("package pkg3: v3:", v3) 7 | } 8 | 9 | // not in expected order 10 | var ( 11 | v3 = c3 12 | // other vars 13 | ) 14 | 15 | const ( 16 | c3 = 100 17 | // other consts 18 | ) 19 | -------------------------------------------------------------------------------- /go-program-anatomy/runtime-vs-buildtime/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | ) 7 | 8 | var ( 9 | hostOS string 10 | hostArch string 11 | ) 12 | 13 | func main() { 14 | fmt.Println("runtime values:", runtime.GOOS, runtime.GOARCH) 15 | fmt.Println("build time values:", hostOS, hostArch) 16 | } 17 | -------------------------------------------------------------------------------- /go-workspace.md: -------------------------------------------------------------------------------- 1 | # Go WORKSPACE & dependency management explained 2 | 3 | Most of Go projects have a specific structure, which from project to project 4 | is pretty much the same. The project normally lives in `$GOPATH` location, 5 | which is the process developers do, right after installing Go binary. 6 | 7 | Right after installing Go binary, it is recommended to correctly set 8 | your `$GOPATH` variable, which most of the times, is set to 9 | `$HOME/go` 10 | 11 | The project layout represented below makes more sense once you start 12 | using third party packages, or your own packages. 13 | 14 | Traditionally third party packages which are hosted remotely 15 | are usually installed using `go get` tool. 16 | 17 | So for example installing `errors` package by `davecheney` 18 | you simply run: 19 | ```bash 20 | go get github.com/pkg/errors 21 | ``` 22 | 23 | This command will reach `github.com/pkg/errors` and place the source code 24 | which will download inside `$GOPATH/src/github.com/pkg/errors` 25 | 26 | If the package contains a main function it will also run 27 | `go install` and create a binary for the downloaded package 28 | 29 | #### Go project layout: 30 | ``` 31 | ├── $GOPATH/ 32 | │ ├── src/ 33 | │ │ ├── github.com/ 34 | │ │ │ ├── organization/ 35 | │ │ │ │ ├── project1/ 36 | │ │ │ │ └── project2/ 37 | │ │ │ ├── user1/ 38 | │ │ │ │ ├── project1/ 39 | │ │ │ │ └── project2/ 40 | │ │ │ ├── pgk/ 41 | │ │ │ └── └── errors/ 42 | │ │ ├── gitlab.com/ 43 | │ │ │ ├── organization/ 44 | │ │ │ │ ├── project1/ 45 | │ │ │ │ └── project2/ 46 | │ │ │ ├── user1/ 47 | │ │ │ │ ├── project1/ 48 | │ │ │ │ └── project2/ 49 | │ │ │ ├── user2/ 50 | │ │ │ │ ├── project1/ 51 | │ │ │ └── └── project2/ 52 | │ │ ├── golang.org/ 53 | │ │ │ ├── x/ 54 | │ │ │ │ ├── crypto/ 55 | │ │ │ │ ├── lint/ 56 | │ │ │ └── └── sys/ 57 | │ ├── bin/ 58 | │ │ ├── goimports 59 | │ │ ├── golint 60 | │ │ ├── binary1 61 | │ │ └── binary2 62 | │ ├── pkg/ 63 | │ │ ├── darwin_amd64/ 64 | │ │ │ ├── github.com/ 65 | │ │ │ │ ├── uber-go/ 66 | │ │ │ │ │ └── atomic.a 67 | │ │ │ │ ├── user1/ 68 | │ │ │ │ │ ├── package1/ 69 | │ │ │ └── └── └── package2/ 70 | │ │ ├── mod/ 71 | │ │ │ ├── github.com/ 72 | │ │ │ │ ├── uber-go/ 73 | │ │ │ │ │ └── zap@1.8.0 74 | │ │ │ │ │ └── zap@1.9.1 75 | │ │ │ └── └── └── ... 76 | │ │ ├── dep/ 77 | │ │ │ ├── sources/ 78 | │ │ │ │ ├── https---github.com-pkg-errors/ 79 | │ │ │ │ │ ├── errors.go 80 | │ │ │ │ │ ├── errors_test.go 81 | │ │ │ │ │ └── ... 82 | │ │ │ │ ├── https---github.com-user1-project1/ 83 | │ │ │ │ │ ├── file1.go 84 | │ │ │ │ │ ├── file1_test.go 85 | │ │ ├── ├── ├── └── ... 86 | │ │ │ │ ├── https---github.com-user2-project1/ 87 | │ │ │ │ │ ├── file1.go 88 | │ │ │ │ │ ├── file1_test.go 89 | │ │ │ │ │ ├── file2.go 90 | │ │ │ │ │ ├── file2_test.go 91 | │ │ └── └── └── └── ... 92 | │ └── 93 | └── 94 | ``` 95 | 96 | ### `$GOPATH` 97 | 98 | `$GOPATH` is the location of Go workspace. In other words, the place 99 | where all Go projects and third party packages will live. 100 | 101 | It is recommended to set `$GOPATH` right after installing Go binary. 102 | Also it is not recommended to have multiple `$GOPATH` variables 103 | when switching projects. 104 | 105 | By simply placing this inside your `.profile` or `.bashrc` or 106 | `.zshrc` depending on which SHELL you use it should set `$GOPATH` correctly 107 | 108 | ```bash 109 | export GOPATH=$HOME/go 110 | ``` 111 | 112 | Go `1.11` introduces modules, which allows users to create projects 113 | and libraries outside `$GOPATH` location. 114 | 115 | Most of the projects out there use `$GOPATH` and it's gonna stay there for a while. 116 | Go modules are something new and definitely worth giving a try. 117 | 118 | They seem to be a good feet for libraries, where less dependencies 119 | are usually required, because Go modules come, with their own 120 | configuration file and a verbosity layer 121 | 122 | ### `src` 123 | 124 | Represents the directory where all the projects' source code and 125 | third party packages will live. So when making a reference to a 126 | third party package or one of your local packages, it will 127 | reference `src` directory. 128 | 129 | The source for a package with the import path `"X/Y/Z"` lives in the directory 130 | `$GOPATH/src/X/Y/Z` 131 | 132 | So importing `errors` package by `davecheney` will look something like: 133 | 134 | ```go 135 | import ( 136 | "os" 137 | "net/http" 138 | 139 | "github.com/pkg/errors" 140 | 141 | "github.com/username/project/package" 142 | ) 143 | ``` 144 | 145 | All of the references to `github.com/...` will be resolved down to 146 | `src` directory where `github.com` lives. 147 | 148 | Notice also that packages like: `os` and `net/http` do not require 149 | this bloated prefix. It's because they are part of standard library. 150 | 151 | Even local packages are referenced using this long path prefix, 152 | hence `github.com/username/project/package` 153 | 154 | Downloading third party packages using `go get` tool, will store packages 155 | in the same `src` location using `git` to clone the repository. 156 | 157 | ### `bin` 158 | 159 | Represents the location where all Go binaries are stored. Usually 160 | when downloading a package using `go get` or when we manually run 161 | `go install` inside the location where we have a main package, in 162 | both cases these operations will result in creating a binary and 163 | storing it inside `$GOPATH/bin` directory which is also represented 164 | by `$GOBIN` environment variable. 165 | 166 | The binary for a command whose source is in `$GOPATH/src/A/B` lives in 167 | `$GOPATH/bin/B` 168 | 169 | Also if `$GOBIN` variable is included in path, you can run any 170 | compiled binary by simply typing their name. 171 | 172 | So a good practice after installing Go binary is to include 173 | `$GOBIN` inside `$PATH` variable so, every binary is easily accessible. 174 | 175 | By simply placing this inside your `.profile` or `.bashrc` or 176 | `.zshrc` depending on which SHELL you use it should set `$GOBIN` correctly. 177 | 178 | ```bash 179 | export GOBIN=$GOPATH/bin 180 | export PATH=$PATH:/$GOBIN 181 | ``` 182 | 183 | ### `pkg` 184 | 185 | Represents the location for package archives, where binaries 186 | needed for a certain package import are stored. If a package is required by 187 | `$GOPATH/src/github.com/username/project` then there is likely a chance, 188 | that package will be stored as an archive file inside `$GOPATH/pkg` 189 | 190 | The binary for a package with the import path `"X/Y/Z"` lives in 191 | `$GOPATH/pkg/$GOOS_$GOARCH/X/Y/Z.a` 192 | 193 | ### `vendor` directory 194 | 195 | The `vendor` directory inside `$GOPATH/host/username/project` is 196 | recognized as a special directory by Go binary tool. And there are 197 | plenty of tools such as `dep` which serve the purpose of package 198 | management. 199 | 200 | `$GOPATH` alone works nice, but when it comes to using different 201 | versions of packages inside a project it fails to do so. 202 | 203 | Because by default `go get` tool will fetch the latest code from `master` 204 | branch and that may be an issue is all of th sudden an issue/bug was 205 | introduced in the latest version of a third party package, which 206 | likely happens very often in the modern web development. 207 | 208 | When Go encounters an import path like `"X/Y/Z"`, it will 209 | try to resolve it in several ways. It will look for a `vendor` 210 | directory first, if it finds any, it will resolve the package from 211 | there, if not it will continue to look in `$GOPATH`. 212 | 213 | For all this `vendor` directory magic to work, it is required 214 | that your project is inside `$GOPATH`, otherwise this will 215 | not work. 216 | 217 | ### `dep` 218 | 219 | `Dep` is a modern Go package manager. For a long period of time 220 | Go did not have any package managers. Meaning that the imported code 221 | from third party packages was always latest version of it. 222 | 223 | Any issue or bug introduced in the third party package would directly affect 224 | the Go project without a way to rollback. Because that was a frequent 225 | problem the community emerged with tools like`glide` and `dep` which are 226 | package managers to address this issue. 227 | 228 | To install `dep` check out the 229 | [Installation Guide](https://golang.github.io/dep/docs/installation.html) 230 | 231 | Running `dep init` will get you started very quickly by generating 232 | `Gopkg.toml` and `Gopkg.lock` files 233 | 234 | Some daily `dep` commands: 235 | 236 | ```bash 237 | # Installs all dependencies listed in "Gopkg.toml" and "Gopkg.lock" 238 | dep ensure 239 | 240 | # Ensures that "errors" & "bar" packages will be installed 241 | dep ensure -add github.com/pkg/errors github.com/foo/bar 242 | 243 | # Ensures that "bar" package will be updated 244 | dep ensure -update github.com/foo/bar 245 | 246 | # Reports if project and dependencies are out of sync 247 | dep check 248 | ``` 249 | 250 | For more info on `dep` check out 251 | [Dep Docs](https://golang.github.io/dep/docs/introduction.html) 252 | 253 | ### Go modules 254 | 255 | Go modules are a new addition to in Go `1.11` where developers are 256 | allowed to write Go code outside `$GOPATH`. This is not an article about 257 | Go modules but the idea is simple, there is a configuration file `go.mod` 258 | which tells Go how to resolve dependencies for a specific package. 259 | 260 | Also a separate tool `go mod` is available for that purpose. 261 | 262 | For more info check out 263 | 264 | [Go Modules](https://github.com/golang/go/wiki/Modules#go-111-modules) 265 | 266 | [Go Modules in 2019](https://blog.golang.org/modules2019) 267 | 268 | ### Notes: 269 | 270 | Usually artifacts inside `bin` and `pkg` are generated and no 271 | developer interaction is required. Basically all developers care about 272 | is `$GOPATH/src` where the source code lives. 273 | 274 | ### For more info check out: 275 | 276 | [How to write Go code](https://golang.org/doc/code.html) 277 | 278 | [GOPATH](https://github.com/golang/go/wiki/GOPATH) 279 | 280 | [Dep](https://golang.github.io/dep/docs/introduction.html) 281 | 282 | [Go Modules](https://github.com/golang/go/wiki/Modules#go-111-modules) 283 | 284 | Back to 285 | [Go Basics](https://github.com/gophertuts/go-basics) 286 | -------------------------------------------------------------------------------- /gophertuts.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 32 | 33 | 34 | 36 | 37 | 38 | 39 | 40 | 41 | 43 | 44 | 45 | 46 | 47 | 48 | 51 | 53 | 54 | 56 | 58 | 59 | 60 | 61 | 62 | 64 | 65 | 66 | 67 | 69 | 71 | 73 | 75 | 76 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /internal-directory/Internal directory.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/internal-directory/Internal directory.key -------------------------------------------------------------------------------- /internal-directory/README.md: -------------------------------------------------------------------------------- 1 | # `internal` directory in Go 2 | 3 | 4 | ## Medium version 📖 5 | 6 | [Go module proxy](https://medium.com/@gophertuts/packages-in-go-df5438123548) 7 | 8 | ### More info 9 | 10 | ```bash 11 | go help importpath 12 | 13 | go help goproxy 14 | ``` 15 | 16 | ## Resources 💎 17 | 18 | - [Go 1.5 vendor experiment](https://go.googlesource.com/proposal/+/master/design/25719-go15vendor.md) 19 | - [Vendor directories](https://golang.org/cmd/go/#hdr-Vendor_Directories) 20 | - [VGO module](https://research.swtch.com/vgo-module) 21 | - [Athens project](https://docs.gomods.io) 22 | - [Athens project - GitHub](https://github.com/gomods/athens) 23 | - [Athens docker image](https://docs.gomods.io) 24 | - [Go project structure](https://vsupalov.com/go-folder-structure/) 25 | - [Go project layout](https://github.com/golang-standards/project-layout) 26 | 27 | ## FEEDBACK ⚗ 28 | 29 | [GopherTuts TypeForm](http://feedback.gophertuts.com) 30 | 31 | ## COMMUNITY 🙌 32 | 33 | [GopherTuts Discord](https://discord.gg/4sgecdh) 34 | 35 | --- 36 | 37 | Back to 38 | [Go Basics](https://github.com/gophertuts/go-basics) 39 | 40 | 41 | -------------------------------------------------------------------------------- /number-systems/Number systems.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/number-systems/Number systems.key -------------------------------------------------------------------------------- /number-systems/Number systems.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/number-systems/Number systems.pdf -------------------------------------------------------------------------------- /number-systems/Number systems.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/number-systems/Number systems.pptx -------------------------------------------------------------------------------- /number-systems/README.md: -------------------------------------------------------------------------------- 1 | # Number systems 2 | 3 | ## Overall topics discussed in this tutorial 4 | 5 | - Base 2 6 | - Base 10 7 | - Base 16 8 | - Conversion from base 10 to N 9 | - Conversion from base N to 10 10 | 11 | ## Resources 💎 12 | 13 | - [Program memory allocation types](https://wiki.osdev.org/Program_Memory_Allocation_Types) 14 | - [Calling convention](https://wiki.osdev.org/Calling_Convention) 15 | - [Memory layout in C](https://www.geeksforgeeks.org/memory-layout-of-c-program/) 16 | - [Zero page](https://en.wikipedia.org/wiki/Zero_page) 17 | - [Go playground exercise](https://play.golang.org/p/RzAfXqZ6XiY) 18 | 19 | ## FEEDBACK ⚗ 20 | 21 | [GopherTuts TypeForm](https://gophertuts.typeform.com/to/j2CJmC) 22 | 23 | ## COMMUNITY 🙌 24 | 25 | [GopherTuts Discord](https://discord.gg/4sgecdh) 26 | 27 | --- 28 | 29 | Back to 30 | [Go Basics](https://github.com/gophertuts/go-basics) 31 | 32 | 33 | -------------------------------------------------------------------------------- /package-management/Package management.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/package-management/Package management.key -------------------------------------------------------------------------------- /package-management/README.md: -------------------------------------------------------------------------------- 1 | # Package management in Go 2 | 3 | ## Resources 💎 4 | 5 | - [Migrating to Go modules](https://blog.golang.org/migrating-to-go-modules) 6 | 7 | ## FEEDBACK ⚗ 8 | 9 | [GopherTuts TypeForm](http://feedback.gophertuts.com) 10 | 11 | ## COMMUNITY 🙌 12 | 13 | [GopherTuts Discord](https://discord.gg/4sgecdh) 14 | 15 | --- 16 | 17 | Back to 18 | [Go Basics](https://github.com/gophertuts/go-basics) 19 | 20 | 21 | -------------------------------------------------------------------------------- /package-management/basic-http/Gopkg.lock: -------------------------------------------------------------------------------- 1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. 2 | 3 | 4 | [[projects]] 5 | digest = "1:abeb38ade3f32a92943e5be54f55ed6d6e3b6602761d74b4aab4c9dd45c18abd" 6 | name = "github.com/fsnotify/fsnotify" 7 | packages = ["."] 8 | pruneopts = "UT" 9 | revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9" 10 | version = "v1.4.7" 11 | 12 | [[projects]] 13 | digest = "1:c0d19ab64b32ce9fe5cf4ddceba78d5bc9807f0016db6b1183599da3dcc24d10" 14 | name = "github.com/hashicorp/hcl" 15 | packages = [ 16 | ".", 17 | "hcl/ast", 18 | "hcl/parser", 19 | "hcl/printer", 20 | "hcl/scanner", 21 | "hcl/strconv", 22 | "hcl/token", 23 | "json/parser", 24 | "json/scanner", 25 | "json/token", 26 | ] 27 | pruneopts = "UT" 28 | revision = "8cb6e5b959231cc1119e43259c4a608f9c51a241" 29 | version = "v1.0.0" 30 | 31 | [[projects]] 32 | digest = "1:84a35669b4b31cc20ffc89c3b2ab32f2189fb2366a973efa1c25e009ef6ae1c6" 33 | name = "github.com/julienschmidt/httprouter" 34 | packages = ["."] 35 | pruneopts = "UT" 36 | revision = "4eec211fa4e8df74ed978dc5681612131854144f" 37 | version = "v1.3.0" 38 | 39 | [[projects]] 40 | digest = "1:5a0ef768465592efca0412f7e838cdc0826712f8447e70e6ccc52eb441e9ab13" 41 | name = "github.com/magiconair/properties" 42 | packages = ["."] 43 | pruneopts = "UT" 44 | revision = "de8848e004dd33dc07a2947b3d76f618a7fc7ef1" 45 | version = "v1.8.1" 46 | 47 | [[projects]] 48 | digest = "1:53bc4cd4914cd7cd52139990d5170d6dc99067ae31c56530621b18b35fc30318" 49 | name = "github.com/mitchellh/mapstructure" 50 | packages = ["."] 51 | pruneopts = "UT" 52 | revision = "3536a929edddb9a5b34bd6861dc4a9647cb459fe" 53 | version = "v1.1.2" 54 | 55 | [[projects]] 56 | digest = "1:bbd3997f0121200f72b64d7a3826eb8a0b910d6a4c19894c9fe2852b9e5eaf3b" 57 | name = "github.com/pelletier/go-toml" 58 | packages = ["."] 59 | pruneopts = "UT" 60 | revision = "8fe62057ea2d46ce44254c98e84e810044dbe197" 61 | version = "v1.5.0" 62 | 63 | [[projects]] 64 | digest = "1:bb495ec276ab82d3dd08504bbc0594a65de8c3b22c6f2aaa92d05b73fbf3a82e" 65 | name = "github.com/spf13/afero" 66 | packages = [ 67 | ".", 68 | "mem", 69 | ] 70 | pruneopts = "UT" 71 | revision = "588a75ec4f32903aa5e39a2619ba6a4631e28424" 72 | version = "v1.2.2" 73 | 74 | [[projects]] 75 | digest = "1:08d65904057412fc0270fc4812a1c90c594186819243160dc779a402d4b6d0bc" 76 | name = "github.com/spf13/cast" 77 | packages = ["."] 78 | pruneopts = "UT" 79 | revision = "8c9545af88b134710ab1cd196795e7f2388358d7" 80 | version = "v1.3.0" 81 | 82 | [[projects]] 83 | digest = "1:1b753ec16506f5864d26a28b43703c58831255059644351bbcb019b843950900" 84 | name = "github.com/spf13/jwalterweatherman" 85 | packages = ["."] 86 | pruneopts = "UT" 87 | revision = "94f6ae3ed3bceceafa716478c5fbf8d29ca601a1" 88 | version = "v1.1.0" 89 | 90 | [[projects]] 91 | digest = "1:524b71991fc7d9246cc7dc2d9e0886ccb97648091c63e30eef619e6862c955dd" 92 | name = "github.com/spf13/pflag" 93 | packages = ["."] 94 | pruneopts = "UT" 95 | revision = "2e9d26c8c37aae03e3f9d4e90b7116f5accb7cab" 96 | version = "v1.0.5" 97 | 98 | [[projects]] 99 | digest = "1:11118bd196646c6515fea3d6c43f66162833c6ae4939bfb229b9956d91c6cf17" 100 | name = "github.com/spf13/viper" 101 | packages = ["."] 102 | pruneopts = "UT" 103 | revision = "b5bf975e5823809fb22c7644d008757f78a4259e" 104 | version = "v1.4.0" 105 | 106 | [[projects]] 107 | digest = "1:a5158647b553c61877aa9ae74f4015000294e47981e6b8b07525edcbb0747c81" 108 | name = "go.uber.org/atomic" 109 | packages = ["."] 110 | pruneopts = "UT" 111 | revision = "df976f2515e274675050de7b3f42545de80594fd" 112 | version = "v1.4.0" 113 | 114 | [[projects]] 115 | digest = "1:ed14edb4b5ec8eff801b1e8217ffaf021729c5a1dee9d940af5bb3302ab7297d" 116 | name = "go.uber.org/multierr" 117 | packages = ["."] 118 | pruneopts = "UT" 119 | revision = "71e610a0e48dbda460d9c18adca8b5f2de04a7c1" 120 | version = "v1.2.0" 121 | 122 | [[projects]] 123 | digest = "1:676160e6a4722b08e0e26b11521d575c2cb2b6f0c679e1ee6178c5d8dee51e5e" 124 | name = "go.uber.org/zap" 125 | packages = [ 126 | ".", 127 | "buffer", 128 | "internal/bufferpool", 129 | "internal/color", 130 | "internal/exit", 131 | "zapcore", 132 | ] 133 | pruneopts = "UT" 134 | revision = "27376062155ad36be76b0f12cf1572a221d3a48c" 135 | version = "v1.10.0" 136 | 137 | [[projects]] 138 | branch = "master" 139 | digest = "1:7c927f17d868be652a4cfe7de23e4292dea5b14d974a1d536e3b7cb7e79fd695" 140 | name = "golang.org/x/sys" 141 | packages = ["unix"] 142 | pruneopts = "UT" 143 | revision = "06d7bd2c5f4f4a6cc6e910b611851044253bd7d1" 144 | 145 | [[projects]] 146 | digest = "1:1093f2eb4b344996604f7d8b29a16c5b22ab9e1b25652140d3fede39f640d5cd" 147 | name = "golang.org/x/text" 148 | packages = [ 149 | "internal/gen", 150 | "internal/triegen", 151 | "internal/ucd", 152 | "transform", 153 | "unicode/cldr", 154 | "unicode/norm", 155 | ] 156 | pruneopts = "UT" 157 | revision = "342b2e1fbaa52c93f31447ad2c6abc048c63e475" 158 | version = "v0.3.2" 159 | 160 | [[projects]] 161 | digest = "1:59f10c1537d2199d9115d946927fe31165959a95190849c82ff11e05803528b0" 162 | name = "gopkg.in/yaml.v2" 163 | packages = ["."] 164 | pruneopts = "UT" 165 | revision = "f221b8435cfb71e54062f6c6e99e9ade30b124d5" 166 | version = "v2.2.4" 167 | 168 | [solve-meta] 169 | analyzer-name = "dep" 170 | analyzer-version = 1 171 | input-imports = [ 172 | "github.com/julienschmidt/httprouter", 173 | "github.com/spf13/viper", 174 | "go.uber.org/zap", 175 | ] 176 | solver-name = "gps-cdcl" 177 | solver-version = 1 178 | -------------------------------------------------------------------------------- /package-management/basic-http/Gopkg.toml: -------------------------------------------------------------------------------- 1 | # Gopkg.toml example 2 | # 3 | # Refer to https://golang.github.io/dep/docs/Gopkg.toml.html 4 | # for detailed Gopkg.toml documentation. 5 | # 6 | # required = ["github.com/user/thing/cmd/thing"] 7 | # ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] 8 | # 9 | # [[constraint]] 10 | # name = "github.com/user/project" 11 | # version = "1.0.0" 12 | # 13 | # [[constraint]] 14 | # name = "github.com/user/project2" 15 | # branch = "dev" 16 | # source = "github.com/myfork/project2" 17 | # 18 | # [[override]] 19 | # name = "github.com/x/y" 20 | # version = "2.4.0" 21 | # 22 | # [prune] 23 | # non-go = false 24 | # go-tests = true 25 | # unused-packages = true 26 | 27 | 28 | [prune] 29 | go-tests = true 30 | unused-packages = true 31 | 32 | [[constraint]] 33 | name = "github.com/julienschmidt/httprouter" 34 | version = "1.3.0" 35 | 36 | [[constraint]] 37 | name = "go.uber.org/zap" 38 | version = "1.10.0" 39 | 40 | [[constraint]] 41 | name = "github.com/spf13/viper" 42 | version = "1.4.0" 43 | -------------------------------------------------------------------------------- /package-management/basic-http/app/app.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "net/http" 7 | "os" 8 | "os/signal" 9 | "time" 10 | 11 | "github.com/julienschmidt/httprouter" 12 | "go.uber.org/zap" 13 | 14 | "github.com/gophertuts/go-basics/package-management/basic-http/config" 15 | "github.com/gophertuts/go-basics/package-management/basic-http/controllers" 16 | "github.com/gophertuts/go-basics/package-management/basic-http/logging" 17 | ) 18 | 19 | type App struct { 20 | Config config.Manager 21 | Router *httprouter.Router 22 | Server http.Server 23 | } 24 | 25 | func New() *App { 26 | err := logging.InitLogger() 27 | if err != nil { 28 | log.Fatal(err) 29 | } 30 | manager, err := config.New() 31 | if err != nil { 32 | logging.Logger.Error("could not initialize config") 33 | } 34 | router := controllers.New() 35 | return &App{ 36 | Config: manager, 37 | Router: router, 38 | } 39 | } 40 | 41 | func (app *App) Start() error { 42 | logging.Logger.Info( 43 | "application started", 44 | zap.String("listen", app.Config.Listen()), 45 | ) 46 | server := http.Server{ 47 | Addr: app.Config.Listen(), 48 | Handler: app.Router, 49 | } 50 | app.Server = server 51 | err := server.ListenAndServe() 52 | if err == http.ErrServerClosed { 53 | logging.Logger.Info("http server is closed") 54 | return nil 55 | } 56 | return err 57 | } 58 | 59 | func (app *App) Shutdown() { 60 | // Need to call Sync() before exiting. See Sync docs 61 | defer logging.Logger.Sync() 62 | ch := make(chan struct{}) 63 | go func() { 64 | logging.Logger.Info("shutting down http server") 65 | if err := app.Server.Shutdown(context.Background()); err != nil { 66 | logging.Logger.Error("error on server shutdown", zap.Error(err)) 67 | } 68 | close(ch) 69 | }() 70 | select { 71 | case <-ch: 72 | logging.Logger.Info("application was shut down") 73 | case <-time.After(2 * time.Second): 74 | logging.Logger.Error("could not shut down in", zap.Duration("timeout", 2 * time.Second)) 75 | } 76 | } 77 | 78 | type Shutdowner interface { 79 | Shutdown() 80 | } 81 | 82 | func ListenForSignals(signals []os.Signal, servers ...Shutdowner) { 83 | c := make(chan os.Signal, 1) 84 | signal.Notify(c, signals...) 85 | sig := <-c 86 | logging.Logger.Info("received shutdown signal", zap.String("signal", sig.String())) 87 | 88 | for _, server := range servers { 89 | server.Shutdown() 90 | } 91 | os.Exit(0) 92 | } 93 | -------------------------------------------------------------------------------- /package-management/basic-http/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import "github.com/spf13/viper" 4 | 5 | const ( 6 | listen = "listen" 7 | ) 8 | 9 | type Manager struct{} 10 | 11 | func New() (Manager, error) { 12 | viper.SetConfigFile("config/config.yaml") 13 | viper.SetConfigType("yaml") 14 | if err := viper.ReadInConfig(); err != nil { 15 | return Manager{}, err 16 | } 17 | return Manager{}, nil 18 | } 19 | 20 | func (m Manager) Listen() string { 21 | return viper.GetString(listen) 22 | } 23 | -------------------------------------------------------------------------------- /package-management/basic-http/config/config.yaml: -------------------------------------------------------------------------------- 1 | listen: "0.0.0.0:8080" 2 | -------------------------------------------------------------------------------- /package-management/basic-http/controllers/index.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | 8 | "github.com/julienschmidt/httprouter" 9 | ) 10 | 11 | func index(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) { 12 | _, err := fmt.Fprint(w, "Welcome to index!\n") 13 | if err != nil { 14 | log.Fatal(err) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /package-management/basic-http/controllers/people.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | 8 | "github.com/julienschmidt/httprouter" 9 | ) 10 | 11 | func people(w http.ResponseWriter, _ *http.Request, ps httprouter.Params) { 12 | _, err := fmt.Fprintf(w, "Hello Mr. %s!\n", ps.ByName(nameParam)) 13 | if err != nil { 14 | log.Fatal(err) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /package-management/basic-http/controllers/routes.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/julienschmidt/httprouter" 5 | ) 6 | 7 | const ( 8 | nameParam = "name" 9 | ) 10 | 11 | func New() *httprouter.Router { 12 | router := httprouter.New() 13 | router.GET("/", index) 14 | router.GET("/people/:name", people) 15 | return router 16 | } 17 | -------------------------------------------------------------------------------- /package-management/basic-http/logging/logger.go: -------------------------------------------------------------------------------- 1 | package logging 2 | 3 | import ( 4 | "go.uber.org/zap" 5 | ) 6 | 7 | var Logger *zap.Logger 8 | 9 | func InitLogger() error { 10 | logger, err := zap.NewProduction() 11 | defer logger.Sync() 12 | if err != nil { 13 | return err 14 | } 15 | Logger = logger 16 | return nil 17 | } 18 | -------------------------------------------------------------------------------- /package-management/basic-http/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "os" 6 | "syscall" 7 | 8 | "github.com/gophertuts/go-basics/package-management/basic-http/app" 9 | ) 10 | 11 | func main() { 12 | application := app.New() 13 | go func() { 14 | err := application.Start() 15 | if err != nil { 16 | log.Fatal(err) 17 | } 18 | }() 19 | app.ListenForSignals([]os.Signal{syscall.SIGINT, syscall.SIGTERM}, application) 20 | } 21 | -------------------------------------------------------------------------------- /package-management/cmd-directory/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /package-management/custom-library/internal/pkg.go: -------------------------------------------------------------------------------- 1 | package internal 2 | -------------------------------------------------------------------------------- /package-management/custom-library/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /package-management/dep/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /package-management/glide/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /package-management/go-mod/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /package-management/internal-directory/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /package-management/package-archives/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /package-management/private-packages/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /package-management/semver/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /package-management/vendor-directory/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /packages/Packages.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/packages/Packages.key -------------------------------------------------------------------------------- /packages/Packages.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/packages/Packages.pdf -------------------------------------------------------------------------------- /packages/Packages.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/packages/Packages.pptx -------------------------------------------------------------------------------- /packages/README.md: -------------------------------------------------------------------------------- 1 | # Packages in Go 2 | 3 | #### Package types 4 | 5 | ```bash 6 | # Displays useful information about import paths 7 | go help importpath 8 | 9 | # cd into package types 10 | cd $GOPATH/src/github.com/gophertuts/go-basics/packages/package-types 11 | 12 | # run the main func inside the main package 13 | go run main.go 14 | 15 | # attempt to run non main package services 16 | # THIS WILL NOT WORK (non main package) 17 | go run services/s1.go 18 | ``` 19 | 20 | #### Helpful information on Packages 21 | 22 | ```bash 23 | go help modules 24 | ``` 25 | 26 | # Medium version 📖 27 | 28 | [Packages in Go](https://medium.com/@gophertuts/packages-in-go-df5438123548) 29 | 30 | ## Resources 💎 31 | 32 | - [Go packages](https://www.callicoder.com/golang-packages/) 33 | - [Naming](https://talks.golang.org/2014/names.slide#1) 34 | - [Package names](https://blog.golang.org/package-names) 35 | - [Code review comments](https://github.com/golang/go/wiki/CodeReviewComments) 36 | - [Migrating to Go modules](https://blog.golang.org/migrating-to-go-modules) 37 | - [Go project structure](https://vsupalov.com/go-folder-structure/) 38 | - [Go project layout](https://github.com/golang-standards/project-layout) 39 | - [Go project layout - Medium](https://medium.com/golang-learn/go-project-layout-e5213cdcfaa2) 40 | - [Best practices for industrial programming](https://youtu.be/PTE4VJIdHPg) 41 | 42 | ## FEEDBACK ⚗ 43 | 44 | [GopherTuts TypeForm](http://feedback.gophertuts.com) 45 | 46 | ## COMMUNITY 🙌 47 | 48 | [GopherTuts Discord](https://discord.gg/4sgecdh) 49 | 50 | --- 51 | 52 | Back to 53 | [Go Basics](https://github.com/gophertuts/go-basics) 54 | 55 | 56 | -------------------------------------------------------------------------------- /packages/cross-reference/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | _ "github.com/gophertuts/go-basics/packages/cross-reference/p1" 7 | ) 8 | 9 | func main() { 10 | fmt.Println("This will not print") 11 | } 12 | -------------------------------------------------------------------------------- /packages/cross-reference/p1/p1.go: -------------------------------------------------------------------------------- 1 | package p1 2 | 3 | import _ "github.com/gophertuts/go-basics/packages/cross-reference/p2" 4 | -------------------------------------------------------------------------------- /packages/cross-reference/p2/p2.go: -------------------------------------------------------------------------------- 1 | package p2 2 | 3 | import _ "github.com/gophertuts/go-basics/packages/cross-reference/p1" 4 | -------------------------------------------------------------------------------- /packages/exported-vs-unexported/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/gophertuts/go-basics/packages/exported-vs-unexported/pkg" 7 | ) 8 | 9 | func main() { 10 | //fmt.Println(pkg.unExported) 11 | fmt.Println(pkg.Exported) 12 | fmt.Println(pkg.Public()) 13 | //fmt.Println(pkg.private()) 14 | } 15 | -------------------------------------------------------------------------------- /packages/exported-vs-unexported/pkg/pkg.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | const ( 4 | unExported = 15 5 | Exported = 10 6 | ) 7 | 8 | func private() string { 9 | return "some public string" 10 | } 11 | 12 | func Public() string { 13 | return "some public string" 14 | } 15 | -------------------------------------------------------------------------------- /packages/go-get/README.md: -------------------------------------------------------------------------------- 1 | # `go get` 2 | 3 | ```bash 4 | # Downloads all referenced dependencies (packages) 5 | # by every package in current directory 6 | go get ./... 7 | 8 | # Downloads latest version (master) of 'pkg' 9 | # with module aware feature on 10 | go get pkg 11 | 12 | # Downloads v1.0.0 of 'pkg' package 13 | go get pkg@v1.0.0 14 | 15 | # Downloads 'pkg' package at git commit hash 16 | go get pkg@af044c0995fe 17 | 18 | # Locks the revision number for this package 19 | # to prevent future breaking changes 20 | go get github.com/lestrrat/go-jwx@b7d4802 21 | cat go.mod 22 | 23 | # Downloads or updates 'pkg' package 24 | go get -u pkg 25 | 26 | # For more info on go get 27 | go help get 28 | ``` 29 | 30 | ### Module aware feature 31 | 32 | In order to turn this feature on you need 33 | to export `GO111MODULE=on` env variable 34 | inside your shell profile 35 | 36 | # `go clean` 37 | 38 | ```bash 39 | # cleans binaries generated with `go build` 40 | # Note: it does not clean the binaries 41 | # generated using `go build -o binary-name` 42 | go clean 43 | 44 | # For more info on go get 45 | go help clean 46 | ``` 47 | 48 | ### Best practices 49 | 50 | - Use `go get ./...` when fetching all dependencies for 51 | a project 52 | - Use `go get pkg` for fetching the latest version 53 | of a package 54 | - Use `go get pkg@v1.0.0` for fetching a specific non 55 | breaking version of the package 56 | Note: `GO111MODULE=on` ENV var should be set to be able 57 | to use module aware feature 58 | -------------------------------------------------------------------------------- /packages/go-get/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gophertuts/go-basics/packages/go-get 2 | 3 | go 1.12 4 | 5 | require github.com/julienschmidt/httprouter v1.3.0 6 | -------------------------------------------------------------------------------- /packages/go-get/go.sum: -------------------------------------------------------------------------------- 1 | github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= 2 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 3 | github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= 4 | github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= 5 | -------------------------------------------------------------------------------- /packages/go-get/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | 8 | "github.com/julienschmidt/httprouter" 9 | ) 10 | 11 | func main() { 12 | router := httprouter.New() 13 | router.GET("/", func(w http.ResponseWriter, req *http.Request, _ httprouter.Params) { 14 | // handle errors bastard 15 | _, _ = fmt.Fprintf(w, "Welcome!") 16 | }) 17 | router.GET("/people/:name", func(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { 18 | name := ps.ByName("name") 19 | // handle errors bastard 20 | _, _ = fmt.Fprintf(w, "Welcome %s", name) 21 | }) 22 | log.Fatal(http.ListenAndServe(":8080", router)) 23 | } 24 | -------------------------------------------------------------------------------- /packages/locals-vs-globals/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | var ( 6 | number = 10.0 7 | delta = .33333 8 | ) 9 | 10 | func main() { 11 | fmt.Println(squareDelta(number)) 12 | } 13 | -------------------------------------------------------------------------------- /packages/locals-vs-globals/square.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func squareDelta(x float64) float64 { 6 | fmt.Println("squaring with delta", delta) 7 | return x * x * delta 8 | } 9 | -------------------------------------------------------------------------------- /packages/multiple-packages/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | //"github.com/gophertuts/go-basics/packages/multiple-packages" 6 | ) 7 | 8 | func main() { 9 | // USING 10 | // go build 11 | // go run *.go 12 | fmt.Println("This will not work") 13 | } 14 | -------------------------------------------------------------------------------- /packages/multiple-packages/pkgA.go: -------------------------------------------------------------------------------- 1 | package pkgA 2 | -------------------------------------------------------------------------------- /packages/multiple-packages/pkgB.go: -------------------------------------------------------------------------------- 1 | package pkgB 2 | -------------------------------------------------------------------------------- /packages/package-naming/anotherWeirdPkg/another-weird.go: -------------------------------------------------------------------------------- 1 | package anotherWeirdPkg 2 | 3 | func W() { 4 | } 5 | -------------------------------------------------------------------------------- /packages/package-naming/collision/collision.go: -------------------------------------------------------------------------------- 1 | package collision 2 | 3 | func New() { 4 | } 5 | -------------------------------------------------------------------------------- /packages/package-naming/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gophertuts/go-basics/packages/package-naming/anotherWeirdPkg" 5 | "github.com/gophertuts/go-basics/packages/package-naming/collision" 6 | "github.com/gophertuts/go-basics/packages/package-naming/redundant" 7 | "github.com/gophertuts/go-basics/packages/package-naming/right" 8 | "github.com/gophertuts/go-basics/packages/package-naming/weird_long_package_name_with_underscores" 9 | ) 10 | 11 | func main() { 12 | // GOOD 13 | redundant.NewMemory() 14 | // BAD 15 | // no need for the word 'Redundant', you already reference the package redundant 16 | redundant.NewRedundantMemory() 17 | 18 | // BAD 19 | weird_long_package_name_with_underscores.F() 20 | anotherWeirdPkg.W() 21 | 22 | // BAD - package and directory names are different 23 | // Don't be afraid of collision as long as the package is different 24 | wrong.New() 25 | collision.New() 26 | } 27 | -------------------------------------------------------------------------------- /packages/package-naming/redundant/redundant.go: -------------------------------------------------------------------------------- 1 | package redundant 2 | 3 | func NewMemory() { 4 | } 5 | 6 | func NewRedundantMemory() { 7 | } 8 | -------------------------------------------------------------------------------- /packages/package-naming/right/wrong.go: -------------------------------------------------------------------------------- 1 | package wrong 2 | 3 | func New() { 4 | } 5 | -------------------------------------------------------------------------------- /packages/package-naming/weird_long_package_name_with_underscores/weird.go: -------------------------------------------------------------------------------- 1 | package weird_long_package_name_with_underscores 2 | 3 | func F() { 4 | } 5 | -------------------------------------------------------------------------------- /packages/package-organization/controllers/c1.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | // THIS IS JUST A PLACEHOLDER 4 | -------------------------------------------------------------------------------- /packages/package-organization/controllers/c1_test.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | // THIS IS JUST A PLACEHOLDER TEST FILE 4 | -------------------------------------------------------------------------------- /packages/package-organization/controllers/c2.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | // THIS IS JUST A PLACEHOLDER 4 | -------------------------------------------------------------------------------- /packages/package-organization/controllers/c2_test.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | // THIS IS JUST A PLACEHOLDER TEST FILE 4 | -------------------------------------------------------------------------------- /packages/package-organization/controllers/controllers.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | // THIS IS JUST A PLACEHOLDER 4 | -------------------------------------------------------------------------------- /packages/package-organization/controllers/controllers_test.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | // THIS IS JUST A PLACEHOLDER TEST FILE 4 | -------------------------------------------------------------------------------- /packages/package-organization/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // THIS IS JUST A PLACEHOLDER 4 | -------------------------------------------------------------------------------- /packages/package-types/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/gophertuts/go-basics/packages/package-types/services" 4 | 5 | func main() { 6 | services.NewS1() 7 | } 8 | -------------------------------------------------------------------------------- /packages/package-types/services/s1.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import "fmt" 4 | 5 | func NewS1() { 6 | fmt.Println("creating new S1 service") 7 | } 8 | -------------------------------------------------------------------------------- /packages/test-packages/pkg1/pkg1.go: -------------------------------------------------------------------------------- 1 | package pkg1 2 | 3 | import "github.com/gophertuts/go-basics/packages/test-packages/pkg2" 4 | 5 | const Exported = pkg2.Exported 6 | -------------------------------------------------------------------------------- /packages/test-packages/pkg1/pkg1_test.go: -------------------------------------------------------------------------------- 1 | package pkg1 2 | 3 | import "github.com/gophertuts/go-basics/packages/test-packages/pkg2" 4 | 5 | const Exported2 = pkg2.Exported2 6 | -------------------------------------------------------------------------------- /packages/test-packages/pkg2/pkg2.go: -------------------------------------------------------------------------------- 1 | package pkg2 2 | 3 | const Exported = 10 4 | -------------------------------------------------------------------------------- /packages/test-packages/pkg2/pkg2_test.go: -------------------------------------------------------------------------------- 1 | package pkg2 2 | 3 | const Exported2 = 10 4 | -------------------------------------------------------------------------------- /vendor-directory/README.md: -------------------------------------------------------------------------------- 1 | # `vendor` directory in Go 2 | 3 | ## Overview 4 | 5 | In this section we'll be talking about the `vendor` directory feature 6 | in Go. 7 | 8 | Since `Go 1.5`, the Go team decided to make our life's easier and allowed the 9 | community to develop package managers, so we all enjoy downloading 10 | and installing specific locked versions of software, without 11 | breaking our precious applications. 12 | 13 | By the end of this tutorial you will perfectly know what the `vendor` 14 | directory is in Go and how to make use of it. 15 | 16 | ## Medium version 📖 17 | 18 | [Vendor directory in Go](https://medium.com/@gophertuts/vendor-directory-in-go-723de6cab46a) 19 | 20 | ### More info 21 | 22 | ```bash 23 | go help importpath 24 | 25 | go help goproxy 26 | ``` 27 | 28 | ## Resources 💎 29 | 30 | - [Go 1.5 vendor experiment](https://go.googlesource.com/proposal/+/master/design/25719-go15vendor.md) 31 | - [Vendor directories](https://golang.org/cmd/go/#hdr-Vendor_Directories) 32 | - [Import path checking](https://golang.org/cmd/go/#hdr-Import_path_checking) 33 | - [Go Modules](https://blog.golang.org/using-go-modules) 34 | - [VGO module](https://research.swtch.com/vgo-module) 35 | - [Athens project](https://docs.gomods.io) 36 | - [Athens project - GitHub](https://github.com/gomods/athens) 37 | - [Athens docker image](https://docs.gomods.io) 38 | - [Go project structure](https://vsupalov.com/go-folder-structure/) 39 | - [Go project layout](https://github.com/golang-standards/project-layout) 40 | 41 | ## FEEDBACK ⚗ 42 | 43 | [GopherTuts TypeForm](http://feedback.gophertuts.com) 44 | 45 | ## COMMUNITY 🙌 46 | 47 | [GopherTuts Discord](https://discord.gg/4sgecdh) 48 | 49 | --- 50 | 51 | Back to 52 | [Go Basics](https://github.com/gophertuts/go-basics) 53 | 54 | 55 | -------------------------------------------------------------------------------- /vendor-directory/Vendor directory.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/vendor-directory/Vendor directory.key -------------------------------------------------------------------------------- /vendor-directory/Vendor directory.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/vendor-directory/Vendor directory.pdf -------------------------------------------------------------------------------- /vendor-directory/Vendor directory.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gophertuts/go-basics/e34dbd4ff13f19903156cd8231df30e98c1999ab/vendor-directory/Vendor directory.pptx -------------------------------------------------------------------------------- /vendor-directory/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/julienschmidt/httprouter" 7 | 8 | _ "github.com/gophertuts/go-basics/vendor-directory/pkg1" 9 | _ "github.com/gophertuts/go-basics/vendor-directory/pkg2" 10 | _ "github.com/gophertuts/go-basics/vendor-directory/pkg3" 11 | ) 12 | 13 | func main() { 14 | fmt.Println("some packages imported") 15 | router := httprouter.New() 16 | fmt.Println("router is just a number:", router) 17 | } 18 | -------------------------------------------------------------------------------- /vendor-directory/pkg1/pkg1.go: -------------------------------------------------------------------------------- 1 | package pkg1 2 | 3 | import "fmt" 4 | 5 | func init() { 6 | fmt.Println("importing pkg1 from $GOPATH") 7 | } 8 | -------------------------------------------------------------------------------- /vendor-directory/pkg2/pkg2.go: -------------------------------------------------------------------------------- 1 | package pkg2 2 | 3 | import "fmt" 4 | 5 | func init() { 6 | fmt.Println("importing pkg2 from $GOPATH") 7 | } 8 | -------------------------------------------------------------------------------- /vendor-directory/pkg3/pkg3.go: -------------------------------------------------------------------------------- 1 | package pkg3 2 | 3 | import "fmt" 4 | 5 | func init() { 6 | fmt.Println("importing pkg3 from $GOPATH") 7 | } 8 | -------------------------------------------------------------------------------- /vendor-directory/vendor/github.com/gophertuts/go-basics/vendor-directory/pkg3/pkg3.go: -------------------------------------------------------------------------------- 1 | package pkg3 2 | 3 | import "fmt" 4 | 5 | func init() { 6 | fmt.Println("importing pkg3 from vendor") 7 | } 8 | -------------------------------------------------------------------------------- /vendor-directory/vendor/github.com/julienschmidt/httprouter/router.go: -------------------------------------------------------------------------------- 1 | package httprouter 2 | 3 | func New() int { 4 | return 10 5 | } 6 | --------------------------------------------------------------------------------