[Golang] Complete Golang Basic Grammar in One Literature

Golang download

Installation package link: https://share.weiyun.com/InsZoHHu

IDE download: https://www.jetbrains.com/go/

The first golang program

package main

import "fmt"

func main() {
   fmt.Println("hello golang")
}

Every executable code must contain the three elements of Package, import and function.

variable

Main function file:

package main

import (
   "awesomeProject/package1"
   "fmt"
)

// 全局变量
var gStr string
var gInt int

func main() {
   // 局部变量
   var lStr string
   var lInt int

   gStr = "out"
   gInt = 100

   lStr = "in"
   lInt = 50

   fmt.Println(gStr)
   fmt.Println(gInt)
   fmt.Println(lStr)
   fmt.Println(lInt)
    
   // 包外函数
   package1.Fun()

   // 包外变量
   package1.Str = "good"
   fmt.Println(package1.Str)
}

The file of the package1 package:

package package1

import (
   "fmt"
)

var Str string

func Fun() {
   fmt.Println("test")
}

Note: golang uses the case of the first letter to distinguish whether it is visible outside the package.

So the Fun() function, Str, which wants to be accessed in the main file, is capitalized.

arrays, slices, dictionaries

package main

import "fmt"

func main() {
   //数组初始化
   var strAry = [10]string{"aa", "bb", "cc", "dd", "ee"}

   //切片初始化
   var sliceAry = make([]string, 0)
   sliceAry = strAry[1:3]

   //字典初始化
   var dic = map[string]int{
      "apple":      1,
      "watermelon": 2,
   }

   // %v 是按照默认格式输出
   fmt.Printf("strAry %+v\n", strAry)
   fmt.Printf("sliceAry %+v\n", sliceAry)
   fmt.Printf("dic %+v\n", dic)
}

Slices point to arrays by indexing. Slices can change the content of an element, but arrays cannot. In development, slices are mainly used for logic processing.

conditional statement

package main

import "fmt"

func main() {
   // 可以通过 := 这种方式直接初始化基础变量
   localStr := "case3"

   if localStr == "case3" {
      fmt.Printf("into ture logic\n")
   } else {
      fmt.Printf("into false logic\n")
   }

   //字典初始化
   var dic = map[string]int{
      "apple":      1,
      "watermelon": 2,
   }

   // 用于检查字典中某个键是否存在,如果存在 num 取键值,ok 取 true,反之 ok 取 false
   if num, ok := dic["orange"]; ok {
      fmt.Printf("orange num %d\n", num)
   }
   if num, ok := dic["watermelon"]; ok {
      fmt.Printf("watermelon num %d\n", num)
   }

   switch localStr {
   case "case1":
      fmt.Println("case1")
   case "case2":
      fmt.Println("case2")
   case "case3":
      fmt.Println("case3")
   default:
      fmt.Println("default")
   }
}

cycle

package main

import "fmt"

func main() {
   for i := 0; i < 5; i++ {
      fmt.Printf("i = %d ", i)
   }
   fmt.Println("")

   j := 0
   for {
      if j == 5 {
         break
      }
      fmt.Printf("j = %d ", j)
      j++
   }
   fmt.Println("")

   // 可以指定初始个数也
   var strAry = []string{"aa", "bb", "cc", "dd", "ee"}

   //切片初始化
   var sliceAry = make([]string, 0)
   sliceAry = strAry[1:3]

   for i, str := range sliceAry {
      fmt.Printf("slice i %d, str %s ", i, str)
   }
   fmt.Println("")

   //字典初始化
   var dic = map[string]int{
      "apple":      1,
      "watermelon": 2,
   }

   for k, v := range dic {
      fmt.Printf("key %s, value %d\n", k, v)
   }
}

The range keyword is used to iterate over iterable data structures such as slices, arrays, and dictionaries.

coroutine

package main

import (
   "fmt"
   "time"
)

func a() {
   time.Sleep(3 * time.Second)
   fmt.Println("it's a")
}

func b() {
   time.Sleep(2 * time.Second)
   fmt.Println("it's b")
}

func c() {
   time.Sleep(1 * time.Second)
   fmt.Println("it's c")
}

func main() {
   go a()
   go b()
   go c()
   time.Sleep(5 * time.Second)
}

As long as the keyword go is used, the three functions a, b, and c can run concurrently.

channel

Key points for channels:

1. Similar to pipes in Linux, first-in-first-out; 2. Thread-safe, multiple goroutines access at the same time, no need to lock; 3. Channel is typed, and an integer channel can only store integers.

Channel definition:

var ch0 chan int
var ch1 chan string
var ch2 chan map[string]string

type stu struct{}

var ch3 chan stu
var ch4 chan *stu

Channels can be used to transfer data between coroutines, and are generally divided into buffered channels and unbuffered channels .

If there is data exchange between two coroutines, channels can be used to transfer them.

package main

import (
   "fmt"
   "time"
)

var ch chan int

func a() {
   time.Sleep(3 * time.Second)
   a := 5
   ch <- a // 发送操作
   fmt.Println("out of a")
}

func b() {
   time.Sleep(1 * time.Second)
   fromA := <-ch // 接收操作
   b := fromA + 3
   fmt.Println("b is ", b)
}

func main() {
   ch = make(chan int, 1)
   go a()
   go b()
   time.Sleep(20 * time.Second)
   fmt.Println("out of main")
}
  1. make(chan int, 1) is used to create a new channel, where chan int indicates that the channel is used to transmit values ​​of integer type.
  2. The 1 after the comma specifies the buffer size for the channel. The buffer size indicates the number of elements that the channel can hold at the same time. In this case, ch is a channel with a buffer size of 1, that is, it can hold at most one integer value at a time.

for example:

When creating a buffered channel, when a send operation (ch <- value) occurs, if the buffer is full, the send operation will be blocked until a receive operation (value = <- ch) reads a value from the buffer. Similarly, when a receive operation (value = <- ch ) occurs, if the buffer is empty, the receive operation will block until a send operation (ch <- value) puts a value into the buffer.

chSync := make(chan int)    // 无缓冲
chAsyn := make(chan int, 1) // 有缓冲

Understanding buffered and unbuffered:

The same is to insert a data into the channel: chSync <-1 No buffering scenario : wait for another coroutine to take over this parameter through <-chSync, then chSync<-1 will continue, otherwise it will be blocked all the time . Buffered scenario : chAsyn<-1 will not block, because the buffer size is 1, only when the second value is put, the first one has not been taken away, then it will block. After careful understanding, this is actually the difference between synchronous and asynchronous. Without buffering, it must be synchronous waiting. With buffering, it will only block when the buffer is full and asynchronous cannot handle it.

for example:

Unbuffered :

package main

import (
   "fmt"
   "time"
)

var ch chan int

func a() {
   time.Sleep(3 * time.Second)
   a := 5
   ch <- a
   fmt.Println("out of a")
}

func b() {
   time.Sleep(1 * time.Second)
}

func main() {
   ch = make(chan int) // 无缓冲管道
   go a()
   go b()
   time.Sleep(20 * time.Second)
   fmt.Println("out of main")
}

output:

out of main

buffered :

package main

import (
   "fmt"
   "time"
)

var ch chan int

func a() {
   time.Sleep(3 * time.Second)
   a := 5
   ch <- a
   fmt.Println("out of a")
}

func b() {
   time.Sleep(1 * time.Second)
}

func main() {
   ch = make(chan int, 1) // 有缓冲管道
   go a()
   go b()
   time.Sleep(20 * time.Second)
   fmt.Println("out of main")
}

output:

out of a
out of main

interface

package main

import "fmt"

// Shape 是接口
type Shape interface {
   Area() float64
   Perimeter() float64
}

type Rect struct {
   height float64
   weight float64
}

func (p *Rect) Area() float64 {
   return p.height * p.weight
}

func (p *Rect) Perimeter() float64 {
   return 2 * (p.height + p.weight)
}

func main() {
   var s Shape = &Rect{height: 10, weight: 8}
   fmt.Println(s.Area())
   fmt.Println(s.Perimeter())
}

In the code, Shape is an interface that declares two methods: Area and Perimeter. We define a specific structure Rect to implement this interface. It can be seen that with the basic Shape interface, one can point to a Rect object and call its method.

Golang only needs to implement all the methods of an interface, then the type is implemented. Therefore, the inheritance relationship of Golang is non-intrusive , which is also the feature and advantage of Golang.

webserver

Write it naked with http:

package main

import (
   "log"
   "net/http"
)

func SayHello(w http.ResponseWriter, r *http.Request) {
   w.Write([]byte("hello")) // 以字符串"hello"作为返回包
}

func main() {
   http.HandleFunc("/say_hello", SayHello)
   err := http.ListenAndServe(":8080", nil) // 开启一个http服务
   if err != nil {
      log.Print("ListenAndServe: ", err)
      return
   }
}

Run it, and then you can visit: http://localhost:8080/say_hello

Write at the end:

The above is the content of this article, thank you for reading.

If you feel that you have gained something, you can give the blogger a like.

If there are omissions or mistakes in the content of the article, please private message the blogger or point it out in the comment area~

Guess you like

Origin blog.csdn.net/Locky136/article/details/132230286