主頁 > 後端開發 > GO 語言快速學習 | PHP轉GO筆記

GO 語言快速學習 | PHP轉GO筆記

2021-06-09 15:57:14 後端開發

web框架

流行度排行

https://github.com/speedwheel/awesome-go-web-frameworks/blob/master/README.md#popularity

beego

https://beego.me/products

echo

https://echo.labstack.com/

gin
go社區檔案

https://learnku.com/docs/gin-gonic/2019

看云gin檔案

https://www.kancloud.cn/shuangdeyu/gin_book/949418

gin快速使用

https://www.jianshu.com/p/98965b3ff638

gin-admin-vue

https://www.gin-vue-admin.com/docs/gorm

官網

https://golang.org/dl/

中文官網

https://go-zh.org/pkg/

go常用庫

https://github.com/jobbole/awesome-go-cn

查看版本號

go version

查看env

go env

拉不下來包

export GOPATH=/usr/local/go/bin
export GOPROXY=https://goproxy.io
export PATH=$PATH:$GOPATH
export GO111MODULE=on

開啟module

go env -w GO111MODULE=on

設定代理

go env -w GOPROXY=https://goproxy.io,direct

微服務框架

go-kit

go micro

go-zero

常用網址

go基礎知識

go基礎知識v1

go基礎知識v2---micro

菜鳥GO

檔案和技術論壇

gomod 詳細使用

go官網庫

go官方pkg中文

github對pgk的使用例子

go mod使用

image

基本資料型別

image

字串操作

image

本地gorm struct生成

https://github.com/xxjwxc/gormt.git

本地struct生成

https://github.com/hantmac/fuckdb.git

1 使用docker-composer方式啟動
2 遇到docker容器不能鏈接本地mysql的時候 
在本地mysql
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;
FLUSH PRIVILEGES

struct 生成

go get -u github.com/gohouse/converter

err := converter.NewTable2Struct().
	SavePath("./model.go").
	Dsn("root:root@tcp(127.0.0.1:3306)/foroo_beta_shopify?charset=utf8").
	TagKey("db").
	EnableJsonTag(true).
	Table("fr_store").
	Run()
fmt.Println(err)
return

基礎

變數或者方法使用小寫相當于protect 首字母大寫 相當于public

使用+來拼接字串

變數宣告 var age int;

常量中的資料型別只可以是布爾型、數字型(整數型、浮點型和復數)和字串型,

可以將 var f string = "Runoob" 簡寫為 f := "Runoob":

函式外的每個陳述句都必須以關鍵字開始(var、const、func等)

:=不能使用在函式外,

_多用于占位,表示忽略值,import _ "./hello" 用_占位只會執行匯入包內的init,其他方法都不能呼叫

iota是go語言的常量計數器,只能在常量的運算式中使用

strconv.Itoa(97) 將一個數字轉成字串型別 string(97)go自帶的會把數字轉換成對應的ascii碼

  const (
            n1 = iota //0
            n2        //1
            n3        //2
            n4        //3
        )

map、slice、chan、指標、interface默認以參考的方式傳遞,

互斥鎖 var lock sync.Mutex

var x int64
var wg sync.WaitGroup
var lock sync.Mutex

func add() {
    for i := 0; i < 5000; i++ {
        lock.Lock() // 加鎖
        x = x + 1
        lock.Unlock() // 解鎖
    }
    wg.Done()
}
func main() {
    wg.Add(2)
    go add()
    go add()
    wg.Wait()
    fmt.Println(x)
}

讀寫互斥鎖 需要注意的是讀寫鎖非常適合讀多寫少的場景,如果讀和寫的操作差別不大,讀寫鎖的優勢就發揮不出來,

var (
    x      int64
    wg     sync.WaitGroup
    lock   sync.Mutex
    rwlock sync.RWMutex
)

func write() {
    // lock.Lock()   // 加互斥鎖
    rwlock.Lock() // 加寫鎖
    x = x + 1
    time.Sleep(10 * time.Millisecond) // 假設讀操作耗時10毫秒
    rwlock.Unlock()                   // 解寫鎖
    // lock.Unlock()                     // 解互斥鎖
    wg.Done()
}

func read() {
    // lock.Lock()                  // 加互斥鎖
    rwlock.RLock()               // 加讀鎖
    time.Sleep(time.Millisecond) // 假設讀操作耗時1毫秒
    rwlock.RUnlock()             // 解讀鎖
    // lock.Unlock()                // 解互斥鎖
    wg.Done()
}

func main() {
    start := time.Now()
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go write()
    }

    for i := 0; i < 1000; i++ {
        wg.Add(1)
        go read()
    }

    wg.Wait()
    end := time.Now()
    fmt.Println(end.Sub(start))
}

sync.Once其實內部包含一個互斥鎖和一個布林值,互斥鎖保證布林值和資料的安全,而布林值用來記錄初始化是否完成,這樣設計就能保證初始化操作的時候是并發安全的并且初始化操作也不會被執行多次,

var icons map[string]image.Image

var loadIconsOnce sync.Once

func loadIcons() {
    icons = map[string]image.Image{
        "left":  loadIcon("left.png"),
        "up":    loadIcon("up.png"),
        "right": loadIcon("right.png"),
        "down":  loadIcon("down.png"),
    }
}

// Icon 是并發安全的
func Icon(name string) image.Image {
    loadIconsOnce.Do(loadIcons)
    return icons[name]
}

goroutine高并發下 操作map 要用 sync.Map 來操作

//sync.Map內置了諸如Store、Load、LoadOrStore、Delete、Range等操作方法
var m = sync.Map{}

func main() {
    wg := sync.WaitGroup{}
    for i := 0; i < 20; i++ {
        wg.Add(1)
        go func(n int) {
            key := strconv.Itoa(n)
            m.Store(key, n)
            value, _ := m.Load(key)
            fmt.Printf("k=:%v,v:=%v\n", key, value)
            wg.Done()
        }(i)
    }
    wg.Wait()
}

代碼中的加鎖操作因為涉及內核態的背景關系切換會比較耗時、代價比較高,針對基本資料型別我們還可以使用原子操作來保證并發安全,因為原子操作是Go語言提供的方法它在用戶態就可以完成,因此性能比加鎖操作更好,Go語言中原子操作由內置的標準庫sync/atomic提供,

// 原子操作版加函式
func atomicAdd() {
    atomic.AddInt64(&x, 1)
    wg.Done()
}

make只用于slice、map以及channel的初始化,回傳的還是這三個參考型別本身

變數之間使用參考地址直接可以改變

package main
func swap(a, b *int) {
	var temp int
	temp = *a
	*a = *b
	*b = temp
}

func main() {
	var a, b = 1, 2
	swap(&a, &b)

	fmt.Println(a)
	fmt.Println(b)
}
//指標小案例
var a int
fmt.Println(&a)
var p *int
p = &a
*p = 20
fmt.Println(a)

在引數賦值時可以不用用一個一個的賦值,可以直接傳遞一個陣列或者切片,特別注意的是在引數后加上“…”即可

package main

import (
    "fmt"
)

func test(s string, n ...int) string {
    var x int
    for _, i := range n {
        x += i
    }

    return fmt.Sprintf(s, x)
}

func main() {
    s := []int{1, 2, 3}
    res := test("sum: %d", s...)    // slice... 展開slice
    println(res)
}

"_"識別符號,用來忽略函式的某個回傳值

沒有引數的 return 陳述句回傳各個回傳變數的當前值,這種用法被稱作“裸”回傳,

func add(a, b int) (c int) {
    c = a + b
    return
}

func calc(a, b int) (sum int, avg int) {
    sum = a + b
    avg = (a + b) / 2

    return
}

func main() {
    var a, b int = 1, 2
    c := add(a, b)
    sum, avg := calc(a, b)
    fmt.Println(a, b, c, sum, avg)
}

命名回傳引數允許 defer 延遲呼叫通過閉包讀取和修改,

defer 是先進后出

package main

func add(x, y int) (z int) {
    defer func() {
        z += 100
    }()

    z = x + y
    return
}

func main() {
    println(add(1, 2)) 
}

定義一維陣列

var a [5]int = [5]int{1,2,5,6,7}
var a = [...]int{1,2,3,5,6}
 d := [...]struct {
        name string
        age  uint8
    }{
        {"user1", 10}, // 可省略元素型別,
        {"user2", 20}, // 別忘了最后一行的逗號,
    }

定義二維陣列 第 2 緯度不能用 "..."

var b [3][2]int = [3][2]int{{1,2},{3,4},{5,6}}
var arr1 [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}

定義slice

全域:
var arr = [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
var slice0 []int = arr[start:end] 
var slice1 []int = arr[:end]        
var slice2 []int = arr[start:]        
var slice3 []int = arr[:] 
var slice4 = arr[:len(arr)-1]      //去掉切片的最后一個元素
區域:
arr2 := [...]int{9, 8, 7, 6, 5, 4, 3, 2, 1, 0}
slice5 := arr[start:end]
slice6 := arr[:end]        
slice7 := arr[start:]     
slice8 := arr[:]  
slice9 := arr[:len(arr)-1] //去掉切片的最后一個元素
//通過make來創建切片
var slice []type = make([]type, len)
slice  := make([]type, len)
slice  := make([]type, len, cap)

定義map

    scoreMap := make(map[string]int)
    scoreMap["張三"] = 90
    scoreMap["小明"] = 100
    // 如果key存在ok為true,v為對應的值;不存在ok為false,v為值型別的零值
    v, ok := scoreMap["張三"]
    if ok {
        fmt.Println(v)
    } else {
        fmt.Println("查無此人")
    }
    //使用delete()函式洗掉鍵值對
      delete(scoreMap, "小明")//將小明:100從map中洗掉

陣列按照下標排序輸出

	tetcc := make(map[int]string,5)
	tetcc[1] = "smallsha"
	tetcc[5] = "smallsha1"
	tetcc[3] = "smallsha2"
	sli := []int{}
	for i := range tetcc {
		sli = append(sli,i)
	}
	sort.Ints(sli)
	for i := 0; i < len(tetcc); i++ {
		fmt.Println("內容",tetcc[sli[i]])
	}

	fmt.Printf("%#v\n", sli)
	return

if判斷

	if test2 :=19; test2> 20 {
		fmt.Println("test11212121212")
	}else if test2 < 20 {
		fmt.Println("test1111")
	}

switch使用

	test3 := 80
	switch test3 {
	case 80:
		fmt.Println("1")
		fallthrough  //可以使用fallthrough強制執行后面的case代碼,
	case 90:
		fmt.Println("2")
	case 100:
		fmt.Println("3")
	default:
		fmt.Println("default")

	}

多個引數呼叫

   func test(s string, n ...int) string {
    var x int
    for _, i := range n {
        x += i
    }

    return fmt.Sprintf(s, x)
}
     s := []int{1, 2, 3}
    res := test("sum: %d", s...)    // slice... 展開slice
    println(res)

閉包使用

func a() func() int  {
	i := 0
	b := func() int{
		i++
		fmt.Println(i)
		return i
	}
	return b
}

	ccccc := a()
	ccccc()
	ccccc()
	return

關鍵字 defer 用于注冊延遲呼叫,

這些呼叫直到 return 前才被執,因此,可以用來做資源清理,

多個defer陳述句,按先進后出的方式執行

慣例是:導致關鍵流程出現不可修復性錯誤的使用 panic,其他使用 error,

func main() {
    test()
}

func test() {
    defer func() {
        if err := recover(); err != nil {
            println(err.(string)) // 將 interface{} 轉型為具體型別,
        }
    }()

    panic("panic error!")
}

運算式

package main

import "fmt"

type User struct {
    id   int
    name string
}

func (self *User) Test() {
    fmt.Printf("%p, %v\n", self, self)
}

func main() {
    u := User{1, "Tom"}
    u.Test()

    mValue := u.Test
    mValue() // 隱式傳遞 receiver

    mExpression := (*User).Test
    mExpression(&u) // 顯式傳遞 receiver
}

定義error
http://www.topgoer.com/方法/自定義error.html

//回傳例外
package main

import (
   "errors"
   "fmt"
)

func getCircleArea(radius float32) (area float32, err error) {
   if radius < 0 {
      // 構建個例外物件
      err = errors.New("半徑不能為負")
      return
   }
   area = 3.14 * radius * radius
   return
}

func main() {
   area, err := getCircleArea(-5)
   if err != nil {
      fmt.Println(err)
   } else {
      fmt.Println(area)
   }
}

//系統拋例外
package main

import "fmt"

func test01() {
   a := [5]int{0, 1, 2, 3, 4}
   a[1] = 123
   fmt.Println(a)
   //a[10] = 11
   index := 10
   a[index] = 10
   fmt.Println(a)
}

func getCircleArea(radius float32) (area float32) {
   if radius < 0 {
      // 自己拋
      panic("半徑不能為負")
   }
   return 3.14 * radius * radius
}

func test02() {
   getCircleArea(-5)
}

//
func test03() {
   // 延時執行匿名函式
   // 延時到何時?(1)程式正常結束   (2)發生例外時
   defer func() {
      // recover() 復活 恢復
      // 會回傳程式為什么掛了
      if err := recover(); err != nil {
         fmt.Println(err)
      }
   }()
   getCircleArea(-5)
   fmt.Println("這里有沒有執行")
}

func test04()  {
   test03()
   fmt.Println("test04")
}

func main() {
   test04()
}
//自定義error
package main

import (
    "fmt"
    "os"
    "time"
)

type PathError struct {
    path       string
    op         string
    createTime string
    message    string
}

func (p *PathError) Error() string {
    return fmt.Sprintf("path=%s \nop=%s \ncreateTime=%s \nmessage=%s", p.path,
        p.op, p.createTime, p.message)
}

func Open(filename string) error {

    file, err := os.Open(filename)
    if err != nil {
        return &PathError{
            path:       filename,
            op:         "read",
            message:    err.Error(),
            createTime: fmt.Sprintf("%v", time.Now()),
        }
    }

    defer file.Close()
    return nil
}

func main() {
    err := Open("/Users/5lmh/Desktop/go/src/test.txt")
    switch v := err.(type) {
    case *PathError:
        fmt.Println("get path error,", v)
    default:

    }

}

interface 應用

// 空介面作為函式引數
func show(a interface{}) {
    fmt.Printf("type:%T value:%v\n", a, a)
}

// 空介面作為map值
    var studentInfo = make(map[string]interface{})
    studentInfo["name"] = "李白"
    studentInfo["age"] = 18
    studentInfo["married"] = false
    fmt.Println(studentInfo)

go調度 sync.WaitGroup

var wg sync.WaitGroup

func hello(i int) {
    defer wg.Done() // goroutine結束就登記-1
    fmt.Println("Hello Goroutine!", i)
}
func main() {

    for i := 0; i < 10; i++ {
        wg.Add(1) // 啟動一個goroutine就登記+1
        go hello(i)
    }
    wg.Wait() // 等待所有登記的goroutine都結束
}

go runtime.Gosched()

//讓出CPU時間片,重新等待安排任務(大概意思就是本來計劃的好好的周末出去燒烤,但是你媽讓你去相親,兩種情況第一就是你相親速度非常快,見面就黃不耽誤你繼續燒烤,第二種情況就是你相親速度特別慢,見面就是你儂我儂的,耽誤了燒烤,但是還饞就是耽誤了燒烤你還得去燒烤)
package main

import (
    "fmt"
    "runtime"
)

func main() {
    go func(s string) {
        for i := 0; i < 2; i++ {
            fmt.Println(s)
        }
    }("world")
    // 主協程
    for i := 0; i < 2; i++ {
        // 切一下,再次分配任務
        runtime.Gosched()
        fmt.Println("hello")
    }
}

runtime.Goexit()

//退出當前協程(一邊燒烤一邊相親,突然發現相親物件太丑影響燒烤,果斷讓她滾蛋,然后也就沒有然后了)
package main

import (
    "fmt"
    "runtime"
)

func main() {
    go func() {
        defer fmt.Println("A.defer")
        func() {
            defer fmt.Println("B.defer")
            // 結束協程
            runtime.Goexit()
            defer fmt.Println("C.defer")
            fmt.Println("B")
        }()
        fmt.Println("A")
    }()
    for {
    }
}

runtime.GOMAXPROCS

//Go1.5版本之后,默認使用全部的CPU邏輯核心數
///兩個任務只有一個邏輯核心,此時是做完一個任務再做另一個任務, 將邏輯核心數設為2,此時兩個任務并行執行,代碼如下,
func a() {
    for i := 1; i < 10; i++ {
        fmt.Println("A:", i)
    }
}

func b() {
    for i := 1; i < 10; i++ {
        fmt.Println("B:", i)
    }
}

func main() {
    runtime.GOMAXPROCS(2)
    go a()
    go b()
    time.Sleep(time.Second)
}

通道

1.對一個關閉的通道再發送值就會導致panic,

2.對一個關閉的通道進行接識訓一直獲取值直到通道為空,

3.對一個關閉的并且沒有值的通道執行接收操作會得到對應型別的零值,

4.關閉一個已經關閉的通道會導致panic,

5.chan<- int是一個只能發送的通道,可以發送但是不能接收;

6 <-chan int是一個只能接收的通道,可以接收但是不能發送,

func counter(out chan<- int) {
    for i := 0; i < 100; i++ {
        out <- i
    }
    close(out)
}

func squarer(out chan<- int, in <-chan int) {
    for i := range in {
        out <- i * i
    }
    close(out)
}
func printer(in <-chan int) {
    for i := range in {
        fmt.Println(i)
    }
}

func main() {
    ch1 := make(chan int)
    ch2 := make(chan int)
    go counter(ch1)
    go squarer(ch2, ch1)
    printer(ch2)
}

通道使用案例

type Job struct {
	Id      int
	RandNum int
}
type Result struct {
	job *Job
	sum int
}

func createPool(num int, jobChan chan *Job,resultChan chan *Result) {
	for i := 0; i < num; i++ {
		go func(jobChan chan *Job,resultChan chan *Result) {
			for i2 := range jobChan {
				r_num := i2.RandNum
				
				var sum int
				for r_num !=0 {
					tmp := r_num % 10
					sum += tmp
					r_num /= 10
				}
				r := &Result{
					job: i2,
					sum: sum,
				}
				resultChan <- r
			}
		}(jobChan,resultChan)
	}
}

func main() {
	flag.Parse()

	jobChan := make(chan *Job, 128)
	resultChan := make(chan *Result, 128)
	createPool(64, jobChan, resultChan)
	// 4.開個列印的協程
	go func(resultChan chan *Result) {
		// 遍歷結果管道列印
		for result := range resultChan {
			fmt.Printf("job id:%v randnum:%v result:%d\n", result.job.Id,
				result.job.RandNum, result.sum)
		}
	}(resultChan)
	var id int
	// 回圈創建job,輸入到管道
	for {
		id++
		// 生成亂數
		r_num := rand.Int()
		job := &Job{
			Id:      id,
			RandNum: r_num,
		}
		jobChan <- job
	}
	return
	}

select 監聽通道

    select {
    case <-chan1:
       // 如果chan1成功讀到資料,則進行該case處理陳述句
    case chan2 <- 1:
       // 如果成功向chan2寫入資料,則進行該case處理陳述句
    default:
       // 如果上面都沒有成功,則進入default處理流程
    }

flag使用 和 os.args

   var name string
	var age int
	var married bool
	var delay time.Duration
	flag.StringVar(&name, "name", "張三", "姓名")
	flag.IntVar(&age, "age", 18, "年齡")
	flag.BoolVar(&married, "married", false, "婚否")
	flag.DurationVar(&delay, "d", 0, "延遲的時間間隔")
	或者使用
    name := flag.String("name", "張三", "姓名")
	age := flag.Int("age", 18, "年齡")
	married := flag.Bool("married", false, "婚否")
	delay := flag.Duration("d", 0, "時間間隔")
	
	
	//決議命令列引數
	flag.Parse()
	fmt.Println(name, age, married, delay)
	//回傳命令列引數后的其他引數
	fmt.Println(flag.Args())
	//回傳命令列引數后的其他引數個數
	fmt.Println(flag.NArg())
	//回傳使用的命令列引數個數
	fmt.Println(flag.NFlag())
	
	
	//os.args
		if len(os.Args) > 0 {
		for index, arg := range os.Args {
			fmt.Printf("args[%d]=%v\n", index, arg)
		}
	}

Log檔案

	logFile, err := os.OpenFile("./smallsha.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		fmt.Println("open log file failed, err:", err)
		return
	}
	log.SetOutput(logFile)  //設定日志檔案寫入
	log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
	log.SetPrefix("[smallsha]")
	log.Printf("%s","smallsha")
	log.Println("test")
	//log.Panic("test1")
	//log.Fatalln("test2")

	logger := log.New(os.Stdout, "<New>", log.Lshortfile|log.Ldate|log.Ltime)
	logger.Println("這是自定義的logger記錄的日志,")

回圈操作

arr := [5]int{1,2,4,5,6,8}
for i,num :=range arr {
    fmt.Println(i,num)
}
//while for 回圈配合通道
	var (
		ch11 = make(chan int)
		ch12 = make(chan int)
	)

	go func() {
		for i := 0; i < 10; i++ {
			ch11 <- i
		}
		close(ch11)
	}()

	go func() {
		for {
			i, ok := <-ch11
			if !ok {
				break
			}
			ch12 <- i * i
		}
		close(ch12)
	}()

	for i := range ch12 {
		 fmt.Println(i)
	}

指標

const MAX int =3
func main(){
    a :=[]int{1,3,5}
    var ptr [MAX]*int;
      for  i = 0; i < MAX; i++ {
      ptr[i] = &a[i] /* 整數地址賦值給指標陣列 */
   }

   for  i = 0; i < MAX; i++ {
      fmt.Printf("a[%d] = %d\n", i,*ptr[i] )
   }
}

strconv 使用

	s3, _ := strconv.ParseBool("1")
	fmt.Printf("%# v\n", pretty.Formatter(s3))
	return
	//int 轉 string
	s2 := 100
	i2 := strconv.Itoa(s2)
	fmt.Printf("%# v\n", pretty.Formatter(i2))
	return
	//string 轉 int
	s1 := "100"
	i1, err := strconv.Atoi(s1)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("%# v\n", pretty.Formatter(i1))
	return

template使用可以注冊http

package logic

import (
	"fmt"
	"html/template"
	"net/http"
)

func init() {
	http.HandleFunc("/",sayHello)
	err := http.ListenAndServe(":9090", nil)
	if err != nil {
		fmt.Println(err)
		return
	}
}
type UserInfo struct {
	Name   string
	Gender string
	Age    int
}

func sayHello(w http.ResponseWriter,r *http.Request)  {
	// 決議指定檔案生成模板物件
	tmpl, err := template.ParseFiles("./hello.html")
	if err != nil {
		fmt.Println("create template failed, err:", err)
		return
	}
	// 利用給定資料渲染模板,并將結果寫入w
	user := UserInfo{
		Name:   "枯藤",
		Gender: "男",
		Age:    18,
	}
	// 利用給定資料渲染模板,并將結果寫入w
	tmpl.Execute(w, user)
}

定義結構體

package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}

func main() {
   var Book1 Books        /* 宣告 Book1 為 Books 型別 */
   var Book2 Books        /* 宣告 Book2 為 Books 型別 */

   /* book 1 描述 */
   Book1.title = "Go 語言"
   Book1.author = "www.runoob.com"
   Book1.subject = "Go 語言教程"
   Book1.book_id = 6495407

   /* book 2 描述 */
   Book2.title = "Python 教程"
   Book2.author = "www.runoob.com"
   Book2.subject = "Python 語言教程"
   Book2.book_id = 6495700

   /* 列印 Book1 資訊 */
   printBook(&Book1)

   /* 列印 Book2 資訊 */
   printBook(&Book2)
}
func printBook( book *Books ) {
   fmt.Printf( "Book title : %s\n", book.title)
   fmt.Printf( "Book author : %s\n", book.author)
   fmt.Printf( "Book subject : %s\n", book.subject)
   fmt.Printf( "Book book_id : %d\n", book.book_id)
}

//結構體new 和賦值
 type Person struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

//宣告構造方法
func newPerson(username string, password string) *Person {
	return &Person{
		Username: username,
		Password: password,
	}
}
//定義修改結構體的方法
func (p *Person) setUsername(username string) {
	p.Username = username
}



map操作

package main

import "fmt"

func main() {
    var countryCapitalMap map[string]string /*創建集合 */
    countryCapitalMap = make(map[string]string)

    /* map插入key - value對,各個國家對應的首都 */
    countryCapitalMap [ "France" ] = "巴黎"
    countryCapitalMap [ "Italy" ] = "羅馬"
    countryCapitalMap [ "Japan" ] = "東京"
    countryCapitalMap [ "India " ] = "新德里"

    /*使用鍵輸出地圖值 */
    for country := range countryCapitalMap {
        fmt.Println(country, "首都是", countryCapitalMap [country])
    }

    /*查看元素在集合中是否存在 */
    capital, ok := countryCapitalMap [ "American" ]
    /*洗掉元素*/ delete(countryCapitalMap, "France")
    /*如果確定是真實的,則存在,否則不存在 */
    /*fmt.Println(capital) */
    /*fmt.Println(ok) */
    if (ok) {
        fmt.Println("American 的首都是", capital)
    } else {
        fmt.Println("American 的首都不存在")
    }
}

宣告變數
    package main
    import "fmt"
    func main() {
        var a string = "Runoob"
        fmt.Println(a)
    
        var b, c int = 1, 2
        fmt.Println(b, c)
    }
    
宣告方法
    package main
    import "fmt"
    func swap(x, y string) (string, string) {
       return y, x
    }
    func main() {
       a, b := swap("Google", "Runoob")
       fmt.Println(a, b)
    }
定義陣列
    var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
    var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
    package main
    import "fmt"
    func main() {
       var n [10]int /* n 是一個長度為 10 的陣列 */
       var i,j int
       /* 為陣列 n 初始化元素 */        
       for i = 0; i < 10; i++ {
          n[i] = i + 100 /* 設定元素為 i + 100 */
       }
       /* 輸出每個陣列元素的值 */
       for j = 0; j < 10; j++ {
          fmt.Printf("Element[%d] = %d\n", j, n[j] )
       }
    }

Go 語言結構體

package main

import "fmt"

type Books struct {
   title string
   author string
   subject string
   book_id int
}

func main() {
   var Book1 Books        /* 宣告 Book1 為 Books 型別 */
   var Book2 Books        /* 宣告 Book2 為 Books 型別 */

   /* book 1 描述 */
   Book1.title = "Go 語言"
   Book1.author = "www.runoob.com"
   Book1.subject = "Go 語言教程"
   Book1.book_id = 6495407

   /* book 2 描述 */
   Book2.title = "Python 教程"
   Book2.author = "www.runoob.com"
   Book2.subject = "Python 語言教程"
   Book2.book_id = 6495700

   /* 列印 Book1 資訊 */
   fmt.Printf( "Book 1 title : %s\n", Book1.title)
   fmt.Printf( "Book 1 author : %s\n", Book1.author)
   fmt.Printf( "Book 1 subject : %s\n", Book1.subject)
   fmt.Printf( "Book 1 book_id : %d\n", Book1.book_id)

   /* 列印 Book2 資訊 */
   fmt.Printf( "Book 2 title : %s\n", Book2.title)
   fmt.Printf( "Book 2 author : %s\n", Book2.author)
   fmt.Printf( "Book 2 subject : %s\n", Book2.subject)
   fmt.Printf( "Book 2 book_id : %d\n", Book2.book_id)
}

結構體作為函式引數
    func printBook( book Books ) {
       fmt.Printf( "Book title : %s\n", book.title)
       fmt.Printf( "Book author : %s\n", book.author)
       fmt.Printf( "Book subject : %s\n", book.subject)
       fmt.Printf( "Book book_id : %d\n", book.book_id)
    }

宣告函式和方法區別

#函式
func main() {
	sum := add(1, 2)
	fmt.Println(sum)
}
 
func add(a, b int) int {
	return a + b
}
#方法
type person struct {
	name string
}
 
func (p person) String() string{
	return "the person name is "+p.name
}

func main() {
	p:=person{name:"張三"}
	fmt.Println(p.String())
}

#可變引數
func main() {
	print("1","2","3")
}

func print (a ...interface{}){
	for _,v:=range a{
		fmt.Print(v)
	}
	fmt.Println()
}

修改字串 需要先轉換成 byte 或者 rune

func changeString() {
    s1 := "hello"
    // 強制型別轉換
    byteS1 := []byte(s1)
    byteS1[0] = 'H'
    fmt.Println(string(byteS1))

    s2 := "博客"
    runeS2 := []rune(s2)
    runeS2[0] = '狗'
    fmt.Println(string(runeS2))
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/285572.html

標籤:PHP

上一篇:GO反射類實體

下一篇:WordPress二次開發難嗎?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more