@zhongdao
2021-03-02T20:35:05.000000Z
字数 13231
阅读 1710
未分类
cat ~/go/src/test/greet.go
package main
import (
"fmt"
"test/util"
)
func main(){
info := util.Info{15}
fmt.Println(info.Age)
fmt.Println(util.Greeting())
}
cat ~/go/src/test/util/util.go
package util
type Info struct{
Age int
}
func Greeting()string{
return "world hello"
}
编译时:
go run greet.go 即可
遇到提示:
go run greet.go
build command-line-arguments: cannot load greet/util: malformed module path "greet/util": missing dot in first path element
说明是go.1.13的高版本,从Go 1.13开始,模块module模式将是所有开发的默认模式。
需要执行如下命令
go mod init
cat greet2.go
package main
import (
"fmt"
)
func main(){
info := Info{15}
fmt.Println(info.Age)
fmt.Println(Greeting())
}
cat util.go
package main
type Info struct{
Age int
}
func Greeting()string{
return "world hello"
}
go run greet2.go util.go 即可
本质是相当于把所有源代码都编译到当前main里面了, main里面通过目录名和package包名来调用。
package main
import (
"fmt"
"test/util"
)
func main(){
info := util.Info{15}
fmt.Println(info.Age)
fmt.Println(util.Greeting())
fmt.Println(util.Greeting2())
fmt.Println(util.Return2(info))
fmt.Println(util.Return(info))
}
util/info.go
package util
type Info struct{
Age int
}
util/util.go
package util
func Greeting()string{
return "world hello "
}
func Return(info Info) int {
return info.Age * 2
}
util/util2.go
package util
func Greeting2()string{
return "world hello 2"
}
func Return2(info Info) int {
return info.Age+2
}
// A Handler responds to an HTTP request.
//
// ServeHTTP should write reply headers and data to the ResponseWriter
// and then return. Returning signals that the request is finished; it
// is not valid to use the ResponseWriter or read from the
// Request.Body after or concurrently with the completion of the
// ServeHTTP call.
//
// Depending on the HTTP client software, HTTP protocol version, and
// any intermediaries between the client and the Go server, it may not
// be possible to read from the Request.Body after writing to the
// ResponseWriter. Cautious handlers should read the Request.Body
// first, and then reply.
//
// Except for reading the body, handlers should not modify the
// provided Request.
//
// If ServeHTTP panics, the server (the caller of ServeHTTP) assumes
// that the effect of the panic was isolated to the active request.
// It recovers the panic, logs a stack trace to the server error log,
// and either closes the network connection or sends an HTTP/2
// RST_STREAM, depending on the HTTP protocol. To abort a handler so
// the client sees an interrupted response but the server doesn't log
// an error, panic with the value ErrAbortHandler.
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
// associate URLs requested to functions that handle requests
http.Handle("/hello/lanre", &HelloWorld{"Lanre"})
http.Handle("/hello/doe", &HelloWorld{"John doe"})
//http.HandleFunc("/", getRequest)
// start web server
log.Fatal(http.ListenAndServe(":9999", nil))
}
type HelloWorld struct {
Name string
}
func (h *HelloWorld) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello "+h.Name)
}
curl http://localhost:9999/hello/dos
package main
import (
"encoding/json"
"fmt"
"strconv"
"net/http"
)
type user struct {
ID int `json:"id"`
Moniker string `json:"moniker"`
Bio string `json:"bio"`
Languages []string `json:"languages`
}
var allUsers []*user
func init() {
allUsers = []*user{
{ID: 1, Moniker: "Hades", Bio: "god of the underworld, ruler of the dead and brother to the supreme ruler of the gods, Zeus", Languages: []string{"Greek"}},
{ID: 2, Moniker: "Horus", Bio: "god of the sun, sky and war", Languages: []string{"Arabic"}},
{ID: 3, Moniker: "Apollo", Bio: "god of light, music, manly beauty, dance, prophecy, medicine, poetry and almost every other thing. Son of Zeus", Languages: []string{"Greek"}},
{ID: 4, Moniker: "Artemis", Bio: "goddess of the wilderness and wild animals. Sister to Apollo and daughter of Zeus", Languages: []string{"Greek"}},
}
}
func main() {
http.Handle("/users/", users{})
http.HandleFunc("/about", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, "You just reached the page of our startup. Thank you for visiting")
})
http.ListenAndServe(":4000", nil)
}
type users struct {
}
func (u users) ServeHTTP(w http.ResponseWriter, r *http.Request) {
s := r.URL.Path[len("/users/"):]
if s != "" {
id, _ := strconv.Atoi(s)
var requestedUser *user
var found bool
for _, v := range allUsers {
if v.ID == id {
found = true //god exists
requestedUser = v
break
}
}
if found {
w.WriteHeader(http.StatusOK)
j, _ := json.Marshal(&requestedUser)
fmt.Fprintf(w, string(j))
return
}
w.WriteHeader(http.StatusNotFound)
return
}
//No id was specified so we return the default
w.WriteHeader(http.StatusOK)
j, _ := json.Marshal(allUsers)
fmt.Fprintf(w, string(j))
}
curl -X GET http://localhost:4000/users/3
curl -X GET http://localhost:4000/users
https://gobyexample.com/http-servers
package main
import (
"fmt"
"net/http"
)
func hello(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "hello\n")
}
func headers(w http.ResponseWriter, req *http.Request) {
for name, headers := range req.Header {
for _, h := range headers {
fmt.Fprintf(w, "%v: %v\n", name, h)
}
}
}
func main() {
http.HandleFunc("/hello", hello)
http.HandleFunc("/headers", headers)
http.ListenAndServe(":8090", nil)
}
go get -u github.com/gorilla/mux
package main
import (
"fmt"
"log"
"net/http"
"github.com/gorilla/mux"
)
func homeLink(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome home!")
}
func main() {
router := mux.NewRouter().StrictSlash(true)
router.HandleFunc("/", homeLink)
log.Fatal(http.ListenAndServe(":8190", router))
}
package main
import (
"fmt"
"time"
)
func numbers() {
for i := 1; i <= 5; i++ {
time.Sleep(250 * time.Millisecond)
fmt.Printf("%d ", i)
}
}
func alphabets() {
for i := 'a'; i <= 'e'; i++ {
time.Sleep(400 * time.Millisecond)
fmt.Printf("%c ", i)
}
}
func main() {
go numbers()
go alphabets()
time.Sleep(3000 * time.Millisecond)
fmt.Println("main terminated")
}
1 a 2 3 b 4 c 5 d e main terminated
https://studygolang.com/articles/12342
第一张蓝色的图表示 numbers 协程,第二张褐红色的图表示 alphabets 协程,第三张绿色的图表示 Go 主协程,而最后一张黑色的图把以上三种协程合并了,表明程序是如何运行的。在每个方框顶部,诸如 0 ms 和 250 ms 这样的字符串表示时间(以微秒为单位)。在每个方框的底部,1、2、3 等表示输出。蓝色方框表示:250 ms 打印出 1,500 ms 打印出 2,依此类推。最后黑色方框的底部的值会是 1 a 2 3 b 4 c 5 d e main terminated,这同样也是整个程序的输出。以上图片非常直观,你可以用它来理解程序是如何运作的。
使用信道需要考虑的一个重点是死锁。当 Go 协程给一个信道发送数据时,照理说会有其他 Go 协程来接收数据。如果没有的话,程序就会在运行时触发 panic,形成死锁。
同理,当有 Go 协程等着从一个信道接收数据时,我们期望其他的 Go 协程会向该信道写入数据,要不然程序就会触发 panic。
package main
func main() {
ch := make(chan int)
ch <- 5
}
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
/tmp/sandbox249677995/main.go:6 +0x80
数据发送方可以关闭信道,通知接收方这个信道不再有数据发送过来。
当从信道接收数据时,接收方可以多用一个变量来检查信道是否已经关闭。
v, ok := <- ch
package main
import (
"fmt"
)
func producer(chnl chan int) {
for i := 0; i < 10; i++ {
chnl <- i
}
close(chnl)
}
func main() {
ch := make(chan int)
go producer(ch)
for { // 无限的 for 循环
v, ok := <-ch
if ok == false {
break
}
fmt.Println("Received ", v, ok)
}
}
for range 循环用于在一个信道关闭之前,从信道接收数据。
接下来我们使用 for range 循环重写上面的代码。
package main
import (
"fmt"
)
func producer(chnl chan int) {
for i := 0; i < 10; i++ {
chnl <- i
}
close(chnl)
}
func main() {
ch := make(chan int)
go producer(ch)
for v := range ch {
fmt.Println("Received ",v)
}
}
在第 16 行,for range 循环从信道 ch 接收数据,直到该信道关闭。一旦关闭了 ch,循环会自动结束。
无缓冲信道的发送和接收过程是阻塞的。
我们还可以创建一个有缓冲(Buffer)的信道。只在缓冲已满的情况,才会阻塞向缓冲信道(Buffered Channel)发送数据。同样,只有在缓冲为空的时候,才会阻塞从缓冲信道接收数据。
func write(ch chan int) {
for i := 0; i < 5; i++ {
ch <- i
fmt.Println("successfully wrote", i, "to ch")
}
close(ch)
}
func main() {
ch := make(chan int, 2)
go write(ch)
time.Sleep(2 * time.Second)
for v := range ch {
fmt.Println("read value", v,"from ch")
time.Sleep(2 * time.Second)
}
}
说明: 对于 有容量的ch 信道, 可以采用 for v:= range ch的 循环来读取。直到 ch关闭。
若用 for range 接收数据时,对于关闭了的信道,会接收完剩下的有效数据,并退出循环。如果没有 close 提示数据发送完毕的话,for range 会接收完剩下所有有效数据后发生阻塞。
WaitGroup 用于实现工作池,因此要理解工作池,我们首先需要学习 WaitGroup。
WaitGroup 用于等待一批 Go 协程执行结束。程序控制会一直阻塞,直到这些协程全部执行完毕。假设我们有 3 个并发执行的 Go 协程(由 Go 主协程生成)。Go 主协程需要等待这 3 个协程执行结束后,才会终止。这就可以用 WaitGroup 来实现。
package main
import (
"fmt"
"sync"
"time"
)
func process(i int, wg *sync.WaitGroup) {
fmt.Println("started Goroutine ", i)
time.Sleep(2 * time.Second)
fmt.Printf("Goroutine %d ended\n", i)
wg.Done()
}
func main() {
no := 3
var wg sync.WaitGroup
for i := 0; i < no; i++ {
wg.Add(1)
go process(i, &wg)
}
wg.Wait()
fmt.Println("All go routines finished executing")
}
var wg sync.WaitGroup
wg.Add() // 添加计数,需要
wg.Done() // 完成的进程
wg.Wait() // 等待所有完成。
注意: &wg ,
Visually Understanding Worker Pool
https://medium.com/coinmonks/visually-understanding-worker-pool-48a83b7fc1f5
select 语句用于在多个发送/接收信道操作中进行选择。select 语句会一直阻塞,直到发送/接收操作准备就绪。如果有多个信道操作准备完毕,select 会随机地选取其中之一执行。该语法与 switch 类似,所不同的是,这里的每个 case 语句都是信道操作。我们好好看一些代码来加深理解吧。
output1 := make(chan string)
output2 := make(chan string)
go server1(output1)
go server2(output2)
select {
case s1 := <-output1:
fmt.Println(s1)
case s2 := <-output2:
fmt.Println(s2)
}
在学习 Mutex 之前,我们需要理解并发编程中临界区(Critical Section)的概念。当程序并发地运行时,多个 Go 协程不应该同时访问那些修改共享资源的代码 (例如: x = x +1 )
根据上下文切换的不同情形,x 的最终值是 1 或者 2。这种不太理想的情况称为竞态条件(Race Condition),其程序的输出是由协程的执行顺序决定的。
如果在任意时刻只允许一个 Go 协程访问临界区,那么就可以避免竞态条件。而使用 Mutex 可以达到这个目的。
Mutex 用于提供一种加锁机制(Locking Mechanism),可确保在某时刻只有一个协程在临界区运行,以防止出现竞态条件。
mutex.Lock()
x = x + 1
mutex.Unlock()
总体说来,当 Go 协程需要与其他协程通信时,可以使用信道。而当只允许一个协程访问临界区时,可以使用 Mutex。
https://blog.golang.org/json-and-go
推荐:
https://yourbasic.org/golang/json-example/
// json.go
package main
import (
"encoding/json"
"fmt"
"net/http"
)
type User struct {
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
Age int `json:"age"`
}
func main() {
http.HandleFunc("/decode", func(w http.ResponseWriter, r *http.Request) {
var user User
json.NewDecoder(r.Body).Decode(&user)
fmt.Fprintf(w, "%s %s is %d years old!", user.Firstname, user.Lastname, user.Age)
})
http.HandleFunc("/encode", func(w http.ResponseWriter, r *http.Request) {
peter := User{
Firstname: "John",
Lastname: "Doe",
Age: 25,
}
json.NewEncoder(w).Encode(peter)
})
http.ListenAndServe(":8080", nil)
}
run:
$ go run json.go
$ curl -s -XPOST -d'{"firstname":"Elon","lastname":"Musk","age":48}' http://localhost:8080/decode
Elon Musk is 48 years old!
$ curl -s http://localhost:8080/encode
{"firstname":"John","lastname":"Doe","age":25}
package main
import (
"encoding/json"
"fmt"
)
// Employee struct with struct tags
type Employee struct {
ID int `json:"id,omitempty"`
FirstName string `json:"firstname"`
LastName string `json:"lastname"`
JobTitle string `json:"job"`
}
func main() {
emp := Employee{
FirstName: "Shiju",
LastName: "Varghese",
JobTitle: "Architect",
}
// Encoding to JSON
data, err := json.Marshal(emp)
if err != nil {
fmt.Println(err.Error())
return
}
jsonStr := string(data)
fmt.Println("The JSON data is:")
fmt.Println(jsonStr)
b := []byte(`{"id":101,"firstname":"Irene","lastname":"Rose","job":"Developer"}`)
var emp1 Employee
// Decoding JSON to a struct type
err = json.Unmarshal(b, &emp1)
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println("The Employee value is:")
fmt.Printf("ID:%d, Name:%s %s, JobTitle:%s", emp1.ID, emp1.FirstName, emp1.LastName,
emp1.JobTitle)
}
output:
The JSON data is:
{"firstname":"Shiju","lastname":"Varghese","job":"Architect"}
The Employee value is:
ID:101, Name:Irene Rose, JobTitle:Developer
package main
import (
"encoding/json"
"fmt"
"os"
)
func main() {
type ColorGroup struct {
ID int
Name string
Colors []string
}
group := ColorGroup{
ID: 1,
Name: "Reds",
Colors: []string{"Crimson", "Red", "Ruby", "Maroon"},
}
b, err := json.Marshal(group)
if err != nil {
fmt.Println("error:", err)
}
os.Stdout.Write(b)
}
package main
import (
"encoding/json"
"fmt"
"os"
)
type response1 struct {
Page int
Fruits []string
}
type response2 struct {
Page int `json:"page"`
Fruits []string `json:"fruits"`
}
func main() {
bolB, _ := json.Marshal(true)
fmt.Println(string(bolB))
intB, _ := json.Marshal(1)
fmt.Println(string(intB))
fltB, _ := json.Marshal(2.34)
fmt.Println(string(fltB))
strB, _ := json.Marshal("gopher")
fmt.Println(string(strB))
slcD := []string{"apple", "peach", "pear"}
slcB, _ := json.Marshal(slcD)
fmt.Println(string(slcB))
mapD := map[string]int{"apple": 5, "lettuce": 7}
mapB, _ := json.Marshal(mapD)
fmt.Println(string(mapB))
res1D := &response1{
Page: 1,
Fruits: []string{"apple", "peach", "pear"}}
res1B, _ := json.Marshal(res1D)
fmt.Println(string(res1B))
res2D := &response2{
Page: 1,
Fruits: []string{"apple", "peach", "pear"}}
res2B, _ := json.Marshal(res2D)
fmt.Println(string(res2B))
byt := []byte(`{"num":6.13,"strs":["a","b"]}`)
var dat map[string]interface{}
if err := json.Unmarshal(byt, &dat); err != nil {
panic(err)
}
fmt.Println(dat)
num := dat["num"].(float64)
fmt.Println(num)
strs := dat["strs"].([]interface{})
str1 := strs[0].(string)
fmt.Println(str1)
str := `{"page": 1, "fruits": ["apple", "peach"]}`
res := response2{}
json.Unmarshal([]byte(str), &res)
fmt.Println(res)
fmt.Println(res.Fruits[0])
enc := json.NewEncoder(os.Stdout)
d := map[string]int{"apple": 5, "lettuce": 7}
enc.Encode(d)
}
output:
$ go run json.go
true
1
2.34
"gopher"
["apple","peach","pear"]
{"apple":5,"lettuce":7}
{"Page":1,"Fruits":["apple","peach","pear"]}
{"page":1,"fruits":["apple","peach","pear"]}
map[num:6.13 strs:[a b]]
6.13
a
{1 [apple peach]}
apple
{"apple":5,"lettuce":7}
package main
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"log"
"os"
"github.com/tidwall/gjson"
"github.com/tidwall/pretty"
"github.com/tidwall/sjson"
)
const jsons = `{"name":{"first":"Janet","last":"Prichard"},"age":47}`
func main() {
jsons, _ := sjson.Set(jsons, "name.last", "Anderson")
jsons, _ = sjson.Set(jsons, "work", "IT manager")
println(jsons)
bjson := pretty.Pretty([]byte(jsons))
println(string(bjson))
ioutil.WriteFile("p_marhsall.json", bjson, os.ModePerm)
/*
jsonstr, _ := getjsonstr("p_marhsall.json")
fmt.Println(gjson.Get(jsonstr, "work").String())
*/
}
https://blog.kowalczyk.info/article/wOYk/advanced-command-execution-in-go-with-osexec.html
go
package main
// https://blog.kowalczyk.info/article/wOYk/advanced-command-execution-in-go-with-osexec.html
// to run:
// go run 01-simple-exec.go
import (
"fmt"
"log"
"os/exec"
"runtime"
)
func main() {
cmd := exec.Command("ls", "-lah")
if runtime.GOOS == "windows" {
cmd = exec.Command("tasklist")
}
out, err := cmd.CombinedOutput()
if err != nil {
log.Fatalf("cmd.Run() failed with %s\n", err)
}
fmt.Printf("combined out:\n%s\n", string(out))
}
package main
import (
"fmt"
"log"
"os/exec"
)
func main() {
cmd := exec.Command("program") // or whatever the program is
cmd.Dir = "C:/usr/bin" // or whatever directory it's in
out, err := cmd.Output()
if err != nil {
log.Fatal(err)
} else {
fmt.Printf("%s", out);
}
}