http://golang.org/doc/ Some package links: http://golang.org/pkg/strings/ http://golang.org/pkg/sync/ http://golang.org/pkg/os/ http://golang.org/pkg/runtime/ http://golang.org/pkg/net/ http://golang.org/pkg/io/ http://golang.org/pkg/fmt/ http://golang.org/pkg/bufio/ HelloWorld package main --------------------------------------import "fmt" func main() { fmt.Printf("hello, world\n") } $ go run hello.go hello, world package main import ( //parenthesis for multiple import or multiple const, etc "fmt" "math" ) func main() { fmt.Println("Happy", math.Pi, "Day") } package main import "fmt" func add(x int, y int) int { //function, type after operand return x + y //When two or more consecutive named function parameters share a type, you can omit the type from all but the last.
} //add(x, y int)func main() { fmt.Println(add(42, 13)) } func split(sum int) (x, y int) { //return multiple named values x = sum * 4 / 9 y = sum - x return } 7 10 var x, y, z int = 1, 2, 3 //var c, python, java = true, false, "no!" := instead of var for implicit types c, python, java := true, false, "no!" (outside a function every construct begins with a keyword and the := construct is not available.) Datatypespackage main import ( "fmt" "math/cmplx" ) var ( ToBe bool = false MaxInt uint64 = 1<<64 - 1 //float: z := float64(1) z := 1.0 z complex128 = cmplx.Sqrt(-5 + 12i) ) const ( Big = 1 << 100 Small = Big >> 99 ) func main() { const f = "%T(%v)\n" fmt.Printf(f, ToBe, ToBe) fmt.Printf(f, MaxInt, MaxInt) fmt.Printf(f, z, z) } bool(false) uint64(18446744073709551615) complex128((2+3i)) bool string int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr byte // alias for uint8 rune // alias for int32 // represents a Unicode code point float32 float64 complex64 complex128 interface that implements one method is ended in "er" e.g. interface Stringer implements method String() In packages a name is exported if it begins with a capital letter. e.g. fmt.Println Numeric constants are high-precision values. An untyped constant takes the type needed by its context. Try printing needInt(Big) too. const ( Big = 1 << 100 Small = Big >> 99 ) func needInt(x int) int { return x*10 + 1 } func needFloat(x float64) float64 { return x * 0.1 }
fmt.Println(needInt(Small)) fmt.Println(needFloat(Small)) fmt.Println(needFloat(Big)) }21 0.2 1.2676506002282295e+29 for/ifsum := 0 for i := 0; i < 10; i++ { // sum := 1 for sum < 1000 {} //for {} forever loop sum += i } if x < 0 { // if v := math.Pow(x, n); v < lim { //a variable only for if (like for for loop) or any of its else blocks return math.Sqrt(-x) + "i" } else { return 0} Switch func main() { switch os := runtime.GOOS; os { case "darwin": fmt.Println("OS X.") case "linux": fmt.Println("Linux.") default: fmt.Printf("%s.", os) } } Switch cases evaluate cases from top to bottom, stopping when a case succeeds. (For example, switch i { does not call f if i==0.) case 0: case f(): } Switch without a condition is the same as switch true. This construct can be a clean way to write long if-then-else chains. case t.Hour() < 12: fmt.Println("Good morning!") case t.Hour() < 17: fmt.Println("Good afternoon.") default: fmt.Println("Good evening.") } Structtype Vertex struct { X int Y int } func main() { v := Vertex{1, 2} to inititalize only one param: d = Vertex{Y:1} v.X = 4 q := &v //pointer q.X = 5 fmt.Println(v, q) } type Vertex struct { X, Y int } var ( p = Vertex{1, 2} // has type Vertex q = &Vertex{1, 2} // has type *Vertex // The special prefix & constructs a pointer to a struct literal. r = Vertex{Y: 1} // X:0 is implicit order is not important s = Vertex{} // X:0 and Y:0 ) func main() { fmt.Println(p, q, r, s) } {1 2} &{1 2} {0 1} {0 0} Slice vs Array []T is a slice with elements of type T. p := []int{2, 3, 5, 7, 11, 13} p[i] p[1:4] //subslice (subarray) len(p), cap(p) //current length, capacity(maximum length) a := make([]int, 5) ==> [0 0 0 0 0] b := make([]int, 0, 5) printSlice("b", b) c := b[:2] printSlice("c", c) d := c[2:5] printSlice("d", d) b len=0 cap=5 [] c len=2 cap=5 [0 0] d len=3 cap=3 [0 0 0] var z []int if z == nil {} A nil slice has a length and capacity of 0 var pow = []int{1, 0, 4, 11, 13} func main() { for i, v := range pow { iterate over a slice and along with valuesskip the index or value by assigning to _ .
for _, value := range pow {} fmt.Printf("%d = %d\n", i, v) } } 0 = 1 1 = 0 2 = 4 3 = 11 4 = 13 Multi-dimensional Slice func Pic(dx, dy int) [][]uint8 { a := make([][]uint8, dy) i :=0 for i < dy{ a[i] = make([]uint8, dx) i=i+1 } for i:=0;i<dy;i = i+1{ for j:= 0; j<dx; j++{ a[i][j] = uint8((i+j)/2) } } return a } var bigDigits = [][]string{ {" 000 ", " 0 0 ", "0 0", "0 0", "0 0", "0 0", " 000 "}, {" 1 ", "11 ", " 1 ", " 1 ", " 1 ", " 1 ", "111"}, {"222","2 2"," 2"," 2 ","2 ","2 ","22222"}, // ... 3 to 8 ... {" 9999", "9 9", "9 9", " 9999", " 9", " 9", " 9"}, } Append x := []int{1,2,3} x = append(x, 4, 5, 6) fmt.Println(x) prints [1 2 3 4 5 6] That is a slice: <<SLICE vs ARRAY>>
And those are arrays:
If you try to compile:
, you will get an error:
as sort.Ints expects to receive a slice []int. Maptype Vertex struct { Lat, Long float64 } var m map[string]Vertex map declarationfunc main() { m = make(map[string]Vertex) instantiate a map vs new for struct m["Bell Labs"] = Vertex{ 40.68433, -74.39967, } fmt.Println(m["Bell Labs"]) } map literal definition var m = map[string]Vertex{ "Bell Labs": Vertex{ 40.68433, -74.39967, }, "Google": Vertex{ 37.42202, -122.08408, }, } var m = map[string]Vertex{ If the top-level type is just a type name, you can omit it from the elements of the literal. "Bell Labs": {40.68433, -74.39967}, "Google": {37.42202, -122.08408}, } set: m[key] = elem get: elem = m[key] Delete: delete(m, key) check: elem, ok = m[key] // If key is in m, ok is true. If not, ok is false and elem is the zero value for the map's element type. Similarly, when reading from a map if the key is not present the result is the zero value for the map's element type. String func Fields(s string) []string split a string by whitespace return a slice of the words functionfunc add(x int, y int) int { //function, type after operand return x + y //When two or more consecutive named function parameters share a type, you can omit the type from all but the last.
} ----- as a value hypot := func(x, y float64) float64 { return math.Sqrt(x*x + y*y) } hypot(3, 4) functions as closures (data type) maintain their local variable values across calls func adder() func(int) int { sum := 0 return func(x int) int { sum += x return sum } } func main() { pos, neg := adder(), adder() for i := 0; i < 10; i++ { fmt.Println( pos(i), neg(-2*i), ) } } // fibonacci is a function that returns a function that returns an int. func fibonacci() func() int { } Implement a fibonacci function that returns a function (a closure) that returns successive fibonacci numbers. // fibonacci is a function that returns // a function that returns an int. func fibonacci() func() int { index := 0 fib := func() int{ f1 := 1 f2 := 1 for i:=0;i<index-1;i=i+1{ temp:=f2 f2=f1+f2 f1=temp } index = index+1 return f2 } return fib } func main() { f := fibonacci() for i := 0; i < 10; i++ { fmt.Println(f()) } } Class or method(function) on struct ******Access Struct inside a function (binde) type Vertex struct { X, Y float64} // The method receiver appears in its own argument list between the func keyword and the method name. func (v *Vertex) Abs() float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y) } func main() { v := &Vertex{3, 4} fmt.Println( v.Abs() ) } 5 &{3 4} In fact, you can define a method on any type you define in your package, not just structs. type MyFloat float64 func (f MyFloat) Abs() float64 { if f < 0 { return float64(-f) } retu rn float64(f) } func main() { f := MyFloat(-math.Sqrt2) fmt.Println(f.Abs()) } The Scale method has no effect when v is a Vertex. Scale mutates v. When v is a value (non-pointer) type, the method sees a copy of the Vertex and cannot mutate the original value. func (v *Vertex) Scale(f float64) { v.X = v.X * f v.Y = v.Y * f } func (v *Vertex) Abs() float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y)} func main() { v := &Vertex{3, 4} v.Scale(5) fmt.Println(v, v.Abs()) } &{15 20} 25 Interface An interface type is defined by a set of methods. A value of interface type can hold any value that implements those methods. type Abser interface { Abs() float64 } func main() { var a Abser f := MyFloat(-math.Sqrt2) v := Vertex{3, 4} a = f // a MyFloat implements Abser a = &v // a *Vertex implements Abser a = v // a Vertex, does NOT // implement Abser fmt.Println(a.Abs()) } type MyFloat float64 func (f MyFloat) Abs() float64 { if f < 0 { return float64(-f) } return float64(f) } type Vertex struct { X, Y float64 } func (v *Vertex) Abs() float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y) } type Reader interface { Read(b []byte) (n int, err error)} type Writer interface { Write(b []byte) (n int, err error)} type ReadWriter interface { //interface embedding Reader Writer } Error An error is anything that can describe itself as an error string. The idea is captured by the predefined, built-in interface type, error, with its single method, Error, returning a string: page 55 Exercise: Errorstype error interface { Error() string } package main import ( "fmt" "time" ) type MyError struct { When time.Time What string } func (e *MyError) Error() string { return fmt.Sprintf("at %v, %s", e.When, e.What) } func run() error { return &MyError{ time.Now(), "it didn't work", } } func main() { if err := run(); err != nil { fmt.Println(err) } } Http import ( Threads"fmt" "net/http" ) type Hello struct{} func (h Hello) ServeHTTP( w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "Hello!") } func main() { var h Hello http.ListenAndServe("localhost:4000", h) } ThreadsGo encourages a different approach in which shared values are passed around on channels and, in fact, never actively shared by separate threads of execution. Only one goroutine has access to the value at any given time. Data races cannot occur, by design. To encourage this way of thinking we have reduced it to a slogan: A goroutine is a lightweight thread managed by the Go runtime. go f(x, y, z) starts a new goroutine running f(x, y, z) The evaluation of f, x, y, and z happens in the current goroutine and the execution of f happens in the new goroutine. func say(s string) { for i := 0; i < 5; i++ { time.Sleep(100 * time.Millisecond) fmt.Println(s) } } func main() { go say("world") say("hello") } //alternate print of hello and world Channel Channels are shared memory w/o need to synchronize threads. c := make(chan int) // Allocate a channel. // Start the sort in a goroutine; when it completes, signal on the channel. go func() { list.Sort() c <- 1 // Send a signal; value does not matter. }() doSomethingForAWhile() <-c // Wait for sort to finish; discard sent value. Receivers always block until there is data to receive.Channels are a typed conduit through which you can send and receive values with the channel operator, <-. ch <- v // Send v to channel ch. (The data flows in the direction of the arrow.) Like maps and slices, channels must be created before use: ch := make(chan int) ci := make(chan int) // unbuffered channel of integers Incoming chan string By default, sends and receives block until the other side is ready. This allows goroutines to synchronize without explicit locks or condition variables. package main import "fmt" func sum(a []int, c chan int) { sum := 0 for _, v := range a { sum += v } c <- sum // send sum to c } func main() { a := []int{7, 2, 8, -9, 4, 0} c := make(chan int) go sum(a[:len(a)/2], c) go sum(a[len(a)/2:], c) x, y := <-c, <-c // receive from c fmt.Println(x, y, x+y) } ch := make(chan int, 100) Sends to a buffered channel block only when the buffer is full. Receives block when the buffer is empty.Modify the example to overfill the buffer and see what happens. package main import "fmt" func main() { c := make(chan int, 1) c <- 1 c <- 2 fmt.Println(<-c) fmt.Println(<-c) } Selectlike switch statement but cases are communication operations. it blocks until one of the cases succeeds and in that case performs the case task. select { case result := <-c: // a new message received fmt.Print(result) case <-timeout: //time out signal received fmt.Print("Timed out\n") return } //waits until either the next result is ready or the timeout occurs HTTP
In the following example, the type go to http://localhost:4000/ to see Hello! Other topicsdefer: schedules a function call (the
deferred function) to be run immediately before the function
executing the defer returns. It's an unusual but
effective way to deal with situations such as resources that must be
released regardless of which path a function takes to return. The
canonical examples are unlocking a mutex or closing a file. ...//parent funciton body defer func(v string) { fmt.Printf(v) }(fruit) ... Triple DotsThe signature of Printf uses the type ...interface{} for its final argument to specify that an arbitrary number of parameters (of arbitrary type) can appear after the format. func Printf(format string, v ...interface{}) (n int, err error) { Within the function Printf, v acts like a variable of type []interface{} but if it is passed to another variadic function, it acts like a regular list of arguments. Here is the implementation of the function log.Println we used above. It passes its arguments directly to fmt.Sprintln for the actual formatting. // Println prints to the standard logger in the manner of fmt.Println. func Println(v ...interface{}) { std.Output(2, fmt.Sprintln(v...)) // Output takes parameters (int, string) } We write ... after v in the nested call to Sprintln to tell the compiler to treat v as a list of arguments; otherwise it would just pass v as a single slice argument. There's even more to printing than we've covered here. See the godoc documentation for package fmt for the details. By the way, a ... parameter can be of a specific type, for instance ...int for a min function that chooses the least of a list of integers: func Min(a ...int) int { min := int(^uint(0) >> 1) // largest int for _, i := range a { if i < min { min = i } } return min } NETpackage main import ( "io" "log" "net" ) func main() { // Listen on TCP port 2000 on all interfaces. l, err := net.Listen("tcp", ":2000") if err != nil { log.Fatal(err) } for { // Wait for a connection. conn, err := l.Accept() if err != nil { log.Fatal(err) } // Handle the connection in a new goroutine. // The loop then returns to accepting, so that // multiple connections may be served concurrently. go func(c net.Conn) { // Echo all incoming data. io.Copy(c, c) // Shut down the connection. c.Close() }(conn) } } ===================================================================== |
Software Engineering ➼ Machine learning ➼ Data Science ➼ Product Leadership 🎯 > Tools - Business > Google >