Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
|
wiki2:go_basics [2017/12/17 18:47] alfred [Interfaces] |
wiki2:go_basics [2020/05/09 09:25] (actual) |
||
|---|---|---|---|
| Línea 32: | Línea 32: | ||
| ''godoc fmt'' \\ | ''godoc fmt'' \\ | ||
| + | ''godoc fmt Println'' \\ | ||
| If you want to get documentation for the fmt package, type the following command in | If you want to get documentation for the fmt package, type the following command in | ||
| the terminal. The godoc tool also provides browsable documentation on a web interface. To access the documentation through a web-based interface, start the web server provided by the godoc tool. Type the following command in the terminal: \\ | the terminal. The godoc tool also provides browsable documentation on a web interface. To access the documentation through a web-based interface, start the web server provided by the godoc tool. Type the following command in the terminal: \\ | ||
| Línea 76: | Línea 77: | ||
| f := "short" | f := "short" | ||
| </code> | </code> | ||
| + | Go also has another shorthand when you need to define multiple variables: | ||
| + | <code> | ||
| + | var ( | ||
| + | a = 5 | ||
| + | b = 10 | ||
| + | c = 15 | ||
| + | ) | ||
| + | </code> | ||
| + | Use the keyword var (or const ) followed by parentheses with each variable on its own line. | ||
| ==== Constantes ==== | ==== Constantes ==== | ||
| <code> | <code> | ||
| Línea 151: | Línea 160: | ||
| x := [5]int{2: 10, 4: 40} // [0 0 10 0 40] | x := [5]int{2: 10, 4: 40} // [0 0 10 0 40] | ||
| </code> | </code> | ||
| + | |||
| + | For example, while ''arr[0:5]'' returns [1,2,3,4,5] , ''arr[1:4]'' returns [2,3,4] . ''arr[0:]'' is the same as ''arr[0:len(arr)]'' , ''arr[:5]'' is the same as ''arr[0:5]'', and ''arr[:]'' is the same as ''arr[0:len(arr)]'' . | ||
| + | |||
| === Slices === | === Slices === | ||
| Línea 508: | Línea 520: | ||
| </code> | </code> | ||
| + | === Pointers === | ||
| + | |||
| + | <code> | ||
| + | func one(xPtr *int) { | ||
| + | *xPtr = 1 | ||
| + | } | ||
| + | func main() { | ||
| + | xPtr := new(int) | ||
| + | one(xPtr) | ||
| + | fmt.Println(*xPtr) // x is 1 | ||
| + | } | ||
| + | </code> | ||
| ==== Interfaces ==== | ==== Interfaces ==== | ||
| Línea 583: | Línea 607: | ||
| The Done method of the WaitGroup type is scheduled to call to tell the main program that the goroutine has executed. The Done method of the WaitGroup type is scheduled to call using the keyword defer. This keyword allows you to schedule other functions to be called when the function returns. In this example, the Done method will be invoked when the goroutine is executed, which ensures that the value of WaitGroup is decremented so the main function can check whether any goroutine is yet to be executed. In the main function, the Wait method of WaitGroup is called, which will check the count of WaitGroup and will block the program until it becomes zero. When the Done method of WaitGroup is called, the count will be decremented by one. At the beginning of the execution, the count is added as 2. When Wait is called, it will wait for the count to turn zero, thereby ensuring that both the goroutines are executed before the program terminates. When the count becomes zero, the program terminates. | The Done method of the WaitGroup type is scheduled to call to tell the main program that the goroutine has executed. The Done method of the WaitGroup type is scheduled to call using the keyword defer. This keyword allows you to schedule other functions to be called when the function returns. In this example, the Done method will be invoked when the goroutine is executed, which ensures that the value of WaitGroup is decremented so the main function can check whether any goroutine is yet to be executed. In the main function, the Wait method of WaitGroup is called, which will check the count of WaitGroup and will block the program until it becomes zero. When the Done method of WaitGroup is called, the count will be decremented by one. At the beginning of the execution, the count is added as 2. When Wait is called, it will wait for the count to turn zero, thereby ensuring that both the goroutines are executed before the program terminates. When the count becomes zero, the program terminates. | ||
| + | |||
| + | The Go runtime scheduler manages the goroutine execution by leveraging the number of OS threads to | ||
| + | attempt goroutine executions simultaneously. The value for the OS threads is taken from the GOMAXPROCS | ||
| + | environment variable. Prior to Go 1.5, the default setting of GOMAXPROCS was 1, meaning that goroutines | ||
| + | were running on a single OS thread by default. (Keep in mind that Go runtime can execute thousands of | ||
| + | goroutines on a single OS thread.) With Go 1.5, the default setting of GOMAXPROCS was changed to the number of CPUs available, as determined by the NumCPU function provided by the runtime package. This default behavior lets the Go programs leverage all available CPU cores for running goroutines in parallel. The value of the GOMAXPROCS can be set by explicitly using the GOMAXPROCS environment variable or by calling runtime. | ||
| + | |||
| + | You can control the GOMAXPROCS setting in your program based on the context of your applications. | ||
| + | Listing 3-19 is a code block that modifies the GOMAXPROCS to one from its default setting: | ||
| + | |||
| + | <code> | ||
| + | import "runtime" | ||
| + | runtime.GOMAXPROCS(1) | ||
| + | </code> | ||
| + | |||
| + | ==== Channels ==== | ||
| + | Sometimes there is a need for communication among goroutines for sending and receiving data, hence the need for synchronization among goroutines. In many programming environments, communication among concurrent programs is complex or limited with features. Go allows you to communicate among goroutines using channels that enable the synchronization of goroutine execution. The built-in make function is used to declare a channel with the help of the keyword chan, followed by the type for specifying the type of data you are using for exchanging data. | ||
| + | |||
| + | A channel of integer type is declared, so integer values will be passed into channels. | ||
| + | <code> | ||
| + | // Unbuffered channel of integers. | ||
| + | count := make(chan int) | ||
| + | // Buffered channel of integers for buffering up to 10 values. | ||
| + | count:= make(chan int, 10) | ||
| + | </code> | ||
| + | |||
| + | When buffered channels are declared, the capacity of channels to hold the data must be specified. If you | ||
| + | try to send more data than its capacity, you get an error. | ||
| + | |||
| + | === Unbuffered === | ||
| + | |||
| + | Unbuffered channels provide synchronous communication among goroutines, which ensures message delivery among them. With unbuffered channels, message sending is permitted only if there is a corresponding receiver that is ready to receive the messages. In this case, both sides of the channel have | ||
| + | to wait until the other side is ready for sending and receiving messages. With buffered channels, a limited | ||
| + | number of messages can be sent into the channel without a corresponding concurrent receiver for receiving those messages. After the messages are sent into buffered channels, those messages from the channel are received. Unlike unbuffered channels, message delivery can’t be guaranteed with buffered channels. | ||
| + | |||
| + | <code> | ||
| + | // Buffered channel of strings. | ||
| + | messages := make(chan string, 2) | ||
| + | // Send a message into the channel. | ||
| + | messages <- "Golang" | ||
| + | </code> | ||
| + | |||
| + | <code> | ||
| + | count := make(chan int) | ||
| + | wg.Add(2) | ||
| + | go printCounts("A", count) | ||
| + | go printCounts("B", count) | ||
| + | count <- 1 | ||
| + | // ... | ||
| + | func printCounts(label string, count chan int) { | ||
| + | defer wg.Done() | ||
| + | for { | ||
| + | val, ok := <-count | ||
| + | if !ok { | ||
| + | fmt.Println("Channel was closed") | ||
| + | return | ||
| + | } | ||
| + | fmt.Printf("Count: %d received from %s \n", val, label) | ||
| + | if val == 10 { | ||
| + | fmt.Printf("Channel Closed from %s \n", label) | ||
| + | close(count) | ||
| + | return | ||
| + | } | ||
| + | val++ | ||
| + | count <- val | ||
| + | } | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | === Buffered channels === | ||
| + | |||
| + | <code> | ||
| + | func main() { | ||
| + | messages := make(chan string, 2) | ||
| + | messages <- "Golang" | ||
| + | messages <- "Gopher" | ||
| + | //Recieve value from buffered channel | ||
| + | fmt.Println(<-messages) | ||
| + | fmt.Println(<-messages) | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | It is a simple example program that demonstrates a buffer channel without having any | ||
| + | goroutines. It creates a messages channel for buffering up to two string values. Values are sent into the | ||
| + | channel until its capacity of two. Because this channel is buffered, values can be sent without depending | ||
| + | on a receiver receiving them. If you try to add more values than its capacity, you will get an error. Once the values are sent into the buffered channel, they can be received from the channel. | ||
| + | |||
| + | ===== No so basic ===== | ||
| + | ==== Annotations (or struct tags) ==== | ||
| + | |||
| + | ===== Standard library ===== | ||
| + | ==== Strings ==== | ||
| + | ==== Dates ==== | ||
| + | <code> | ||
| + | time.Date(1970, time.January, 10, 0, 0, 0, 0, time.UTC) | ||
| + | </code> | ||
| + | ==== Time ==== | ||
| + | <code> | ||
| + | time.Sleep(time.Duration(sleep) * time.Millisecond) | ||
| + | </code> | ||
| + | |||
| + | ==== Rand ==== | ||
| + | <code> | ||
| + | sleep := rand.Int63n(1000) | ||
| + | </code> | ||
| + | |||
| + | ===== Notes ===== | ||
| + | ==== Install last version ==== | ||
| + | |||
| + | <code> | ||
| + | wget https://storage.googleapis.com/golang/go1.9.2.linux-amd64.tar.gz | ||
| + | sudo tar -xvf go1.9.2.linux-amd64.tar.gz | ||
| + | sudo mv go /usr/local | ||
| + | export GOROOT=/usr/local/go | ||
| + | sudo ln -s /usr/local/go/bin/go /usr/bin/go | ||
| + | sudo ln -s /usr/local/go/bin/godoc /usr/bin/godoc | ||
| + | sudo ln -s /usr/local/go/bin/gofmt /usr/bin/gofmt | ||
| + | </code> | ||
| + | |||
| + | ==== Config VS Code to develop in Go ==== | ||
| + | You will need to install the 'golang' package. Also, when it is enabled, let it install the other tools. | ||
| + | |||
| + | If you wanted to debug you should change into the configuration the next variable (specially if only had a main.go file): | ||
| + | <code> | ||
| + | "program": "${workspaceRoot}", | ||
| + | </code> | ||
| + | A full example is: | ||
| + | <code> | ||
| + | { | ||
| + | // Use IntelliSense to learn about possible attributes. | ||
| + | // Hover to view descriptions of existing attributes. | ||
| + | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
| + | "version": "0.2.0", | ||
| + | "configurations": [ | ||
| + | { | ||
| + | "name": "Launch", | ||
| + | "type": "go", | ||
| + | "request": "launch", | ||
| + | "mode": "auto", | ||
| + | "program": "${workspaceRoot}", | ||
| + | "env": {}, | ||
| + | "args": [], | ||
| + | "showLog": true | ||
| + | } | ||
| + | ] | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | |||
| + | ====== Go Web programming ====== | ||
| + | ===== Basics ===== | ||
| + | ==== Http server ==== | ||
| + | <code> | ||
| + | package main | ||
| + | import ( | ||
| + | "net/http" | ||
| + | ) | ||
| + | func main() { | ||
| + | mux := http.NewServeMux() | ||
| + | fs := http.FileServer(http.Dir("public")) | ||
| + | mux.Handle("/", fs) | ||
| + | http.ListenAndServe(":8080", mux) | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | |||
| + | |||
| + | ====== Go Libraries ====== | ||
| + | ===== GORM ===== | ||
| + | * ''go get -u github.com/jinzhu/gorm'' | ||
| + | * ''go get -u github.com/go-sql-driver/mysql'' | ||
| + | |||
| + | <code> | ||
| + | package main | ||
| + | |||
| + | import ( | ||
| + | "github.com/jinzhu/gorm" | ||
| + | _ "github.com/jinzhu/gorm/dialects/mysql" | ||
| + | "fmt" | ||
| + | ) | ||
| + | |||
| + | type Person struct { | ||
| + | ID uint `json:"id""` | ||
| + | FirstName string `json:"firstname"` | ||
| + | LastName string `json:"lastname""` | ||
| + | } | ||
| + | |||
| + | func main() { | ||
| + | db, err := gorm.Open("mysql", "root:pass@/test?charset=utf8&parseTime=True&loc=Local") | ||
| + | if err != nil { | ||
| + | fmt.Println(err) | ||
| + | } | ||
| + | defer db.Close() | ||
| + | |||
| + | db.AutoMigrate(&Person{}) | ||
| + | |||
| + | p1 := Person{FirstName: "John", LastName: "Doe"} | ||
| + | p2 := Person{FirstName: "Jane", LastName: "Smith"} | ||
| + | |||
| + | db.Create(&p1) | ||
| + | db.Create(&p2) | ||
| + | |||
| + | var p3 Person | ||
| + | db.First(&p3) | ||
| + | |||
| + | fmt.Println(p1.LastName) | ||
| + | fmt.Println(p2.LastName) | ||
| + | fmt.Println(p3.LastName) | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | ===== Gin ===== | ||
| + | * ''go get github.com/gin-gonic/gin'' | ||
| + | <code> | ||
| + | package main | ||
| + | |||
| + | import ( | ||
| + | "github.com/gin-gonic/gin" | ||
| + | "fmt" | ||
| + | ) | ||
| + | |||
| + | func main() { | ||
| + | r := gin.Default() | ||
| + | r.GET("/", func(c *gin.Context) { | ||
| + | c.JSON(200, gin.H{ | ||
| + | "message": "Hello World", | ||
| + | }) | ||
| + | }) | ||
| + | r.Run() | ||
| + | } | ||
| + | </code> | ||
| + | |||
| + | ==== Examble GORM + GIN ==== | ||
| + | * [[go_lib:examples:gormgin]] | ||
| + | |||