Golang基础 | 青训营笔记

77 阅读5分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第1天

变量

  1. 定义变量
// 显示声明
var str1 string = "hello go!"
// 关键字 变量名 变量类型=变量值
// 隐式声明
str2 := "hello go twice!"
  1. 引用一个包
  1. 一个文件夹里不能出现多个包,即只能有一个包。但是一个文件夹可以有多个文件,多个文件可以使用同一包名,但要注意变量不能冲突。
  2. 包里只有大写的变量和函数才能被其他包引用,即大写的是public,小写的是private。
package main

import(
	"fmt",
    "goclass/selfpackage"
    //cool "goclass/selfpackage"
    //."goclass/selfpackage"
)
// 在selfpackage定义了一个变量A,在main包里引入。有三种引入方式,分别对应三种使用方式,第二种是给包起个别名。第一种最常用。
fmt.Println(selfpackage.A)
// fmt.Println(cool.A)
// fmt.Println(A)
  1. 数据类型

常用的:

    • unit
    • int
    • float64
    • bool

fmt.Printf("%T",num) 打印num的数据类型。

  1. 数据类型的转换
    1. string -> int int, err := strconv.Atoi(string)
    2. string -> int64 int64, err := strconv.ParseInt(string,10,64)
    3. int -> string string := strconv.Itoa(int)
    4. int64 -> string string := strconv.FormatInt(int64,10)
    5. 字符串到float32/float64 float32, err = ParseFloat(string,32) floast64, err = ParseFloat(string, 64)
  1. 复杂数据类型

结构(struct),接口(interface),数组[数组长度] 值类型{值1, 值2},切片(slice) []值类型{值1,值2} ,map [key类型]值类型{key:值},指针 *,函数 func,管道 chan

控制语句

  1. 递增递减语句

自增++ 自减 --

  1. if-else

和C++/java的使用方法一样

if(){

}else{

}
// 多分支
if(){

}else if(){

}else if(){

}else{

}
  1. switch

和C++用法一样,但是没有break(但是自带break功能),如果switch只会执行第一个满足的case条件下的代码块。如果想继续打印需要在下面加fallthrough关键字(即使条件不满足也会执行)。

a := 1
	switch a{
	case 0 :
		fmt.Println(0)
	case 1 :
		fmt.Println(1)
	case 2:
		fmt.Println(3)
	default:
		fmt.Println("other") 	
	}
a := 60
	switch {
	case a>20:
		fmt.Println("大于20")
		fallthrough
	case a>40:
		fmt.Println("大于40")
	default:
		fmt.Println("小于20")
	}
  1. 循环
// 死循环
for{
	
}

//正常的for循环
for a:=1;a<10;a++{
	fmt.Println(a)
}

数组和切片

G数组和切片的区别:blog.csdn.net/qq_41893274…

数组时定长的,切片是变长的。

a := [3]int{0,1,2}
b := [...]int{1,2,3,4,5,6}

# 先声明数组
var c = new([10]int)
c[5] = 3

# 遍历数组的方式 len(c) == cap(c)
for i:=0;i<len(c);i++{
	fmt.Println(b[i])
}

// i,v分别是下标和值
for i, v := range c{
	fmt.Println(i,v)
}

// 二维数组
d := [3][3]int{
	{0,1,2},
	{3,4,5},
	{6,7,8}
}
  1. 切片

不固定长度的数组。和python列表的slice一样。(好吧,打脸了,还是有区别的。)

Go的切片的值修改会影响原来的数组,python不会。

python的切片是浅拷贝,但是只有嵌套的列表值修改才会影响原来的值。Go的slcie是浅拷贝

更多关于Go的复制可阅读:

blog.csdn.net/weixin_4421…

arr := [...]int{1,2,3,4,5,6}
	fmt.Println("arr初值", arr)
	arr2 := arr[:3]
	fmt.Println("arr2的值", arr2)
	arr2[0] = 7
	fmt.Println("arr的第一个值通过切片arr2改变了",arr)

// 创建切片
// 切片是空的,没有初始化
var aa []int
// 4是切片,6是size,make是有默认的值
aaa := make([]int,4,6)
  • append
a := [3]int{1,2,3}
c := a
c = append(c, 4)
c = append(c,5)
  • copy(c1,c2)

把c2复制到c2位置对应c1的位置,如果想指定c1的位置,可以用切片指定复制范围。

a := [3]int{1,2,3}
c := a[2:]
// 复制到a的第一项
copy(a,c)
// 复制到a的第二项
copy(a[1:2],c)
  • map

与其他语言key-value数据结构不同的是key可以不是string 类型。

// 显示说明
var m map[string]string
m = map[string]string{}

m["name"]="coder-zc"
m["sex"]="男"

// 隐式声明
m1 := map[string]string{}



m2 := make(map[string]string)

// 任意类型
m3 := map[int]interface{}

m1 := map[int]interface{}{}
	m1[1] = 22
	m1[2] = "zc"
	m1[3] = [3]string{"python","java","go"}
	fmt.Println(m1, len(m1))
	delete(m1, 2)
	fmt.Println(m1, len(m1))


// 遍历map
for k, v := range m1{
	fmt.Println(k,v)
}

函数

关键字 func

func a(d1 int, d2 string)(ret1 int, ret2 string){
	if(d1>1){
        return d1, "大于1"
        fmt.Println(d1)
    }else{
        fmt.Println(d2)
        return d2, "小于等于1"
    }
}
func a(d1 int, d2 string)(ret1 int, ret2 string){
	ret1 = d1
    ret2 = d2
    // return省略了ret1,ret2,因为返回值已经指定了。
    return
}
// 匿名函数可以写在函数里面

func main(){
	b := func(data1 string){
        fmt.Println(data1)
    }
    b("我是匿名函数")
}

// 等价于

func bb(data1 string){
        fmt.Println(data1)
    }
func main(){
	b := bb
    b("我是匿名函数")
}
  • 不定项参数
func more(data1 int, data2 ...string){
    fmt.Println(data1, data2)
}

// data2是一个切片数组,对不定项参数进行for循环
for k,v := range data2{
    fmt.Println(k,v)
}

// 将切片的数据传入不定项参数
arr := []string{"1","2","3"}
more(data1,arr...)
  • 定义函数同时执行
func main(){
    (func(){
        fmt.Println("我在这里执行,别人都别管我")
    })()
}
  • 闭包

函数返回一个函数

func mo()func(int){
    return func(int){
        
    }
}
  • 闭包函数的调用
func mo()func(int){
    return func(num int){
        fmt.println("闭包函数",num)
    }
}

func main(){
    mo()(4)
}
  • 延迟调用函数
func mo(){
    fmt.Println("我想最先执行")
}

func main(){
	defer mo()
    fmt.Println("1")
    fmt.Println("2")
    fmt.Println("3")
}

指针和地址

package main

import "fmt"

func main(){
	var a int
    a = 123
    fmt.Println(a)
    var b *int
    b = &a
    *b = 999
    fmt.Println(a,b)
    
}
// 数组指针和指针数组
	var arr [5]string
	arr = [5]string{"1,2,3,4"}
	// 数组的指针
	var arrP *[5]string
	arrP = &arr
	fmt.Println(arr, arrP)

	var arrPP [5]*string 
	var str1 string = "str1"
	var str2 string = "str2"
	var str3 string = "str3"
	var str4 string = "str4"
	var str5 string = "str5"
	arrPP = [5]*string{&str1,&str2,&str3,&str4,&str5}
	*arrPP[2] = "555"
	fmt.Println(str3)
  • 结构体
package main

import "fmt"

type Person struct{
    Name string
    Age int
    Sex bool
    Hobby []string
}

func main(){
    // 显示定义
    var zc Person
    zc.Age = 18
    zc.Name = "zc"
    zc.Sex = true
    zc.Hobbys = []string{"唱","跳","rap"}
    // 隐式声明
    zc := Person{"zc",18,true,[]string{"唱","跳","rap"}}
    fmt.Println(zc)
}
  • 结构体的方法
func (p *Person)Song(name string)(res string){
    res = "鸡你太美"
    fmt.Printf("%v唱了一首%v,观众觉得%v",q.Name, name, res)
    return
}

接口

type Animal interface{
	Shout()
	Run()
}

type Dog struct{
	Name string
}

type Cat struct{
	Name string
}

func (c Cat)Shout(){
	fmt.Println("猫在叫")
}

func (d *Dog)Shout(){
	fmt.Printf("%v狗在叫\n",d.Name)
}

并发-goroutine和channel

在调用一个方法的前面加上go就是goroutine,它会让方法异步执行,相当于协程。

协程管理器:

func Run(){
    fmt.Println("我跑起来了)
}


func main(){
    go Run()
    i := 0
    for i<10;i++{
        fmt.Println(i)
    }
}
var wg sync.WaitGroup
wg.Add()
wg.Done()
wg.Wait()
package main

import (
	"fmt"
	"sync"
)

func main(){
	var wg sync.WaitGroup
	wg.Add(1)
	go Run(&wg)
	wg.Wait()
}

func Run(wg *sync.WaitGroup){
	fmt.Println("我跑起来了")
	wg.Done()
}
  • channel

可分为五种。

可读可取,c:=make(chan int)

可读 var readChan <- chan int = c

可取 var setChan chan<- int = c

有缓冲 c:=make(chan int, 5)

无缓冲

// 无缓冲区的channel
// 可手动调试看执行过程
c1 := make(chan int)

	go func(){
		for i:=0;i<10;i++{
			c1<-i
		}
	}()
	for i:=0;i<10;i++{
		fmt.Println(<-c1)
	}

// 有缓冲区的channel
c1 := make(chan int,10)

	go func(){
		for i:=0;i<10;i++{
			c1<-i
		}
	}()
	for i:=0;i<10;i++{
		fmt.Println(<-c1)
	}

// 结果虽然相同,但执行过程不一样
c2 := make(chan int, 5)
	c2 <- 1
	c2 <- 2
	c2 <- 3
	//提前关闭会报错
	close(c2)
	c2 <- 4
	c2 <- 5
	for i:=0;i<5;i++{
		fmt.Println(<-c2)
	}
c2 := make(chan int, 5)
	c2 <- 1
	c2 <- 2
	c2 <- 3
	c2 <- 4
	c2 <- 5
	// 如果需要for range的话channel必须关闭
	close(c2)
	for v:= range c2{
		fmt.Println(v)
	}
func main(){
    c := make(chan int)
	var readc <-chan int = c
	var writec chan<- int = c
	go SetChan(writec)
	GetChan(readc)
}

func SetChan(writec chan<- int){
	for i:=0;i<10;i++{
		// fmt.Println("我在set函数里面")
		writec<-i
	}
	
}
// getchan里输出的值,永远是setchan通道写入的值
func GetChan(readc <-chan int){
	for i:=0;i<10;i++{
		fmt.Printf("我在get函数里面取出来从set函数返回给我的一个信息,它是%v\n",<-readc)
	}
	
}

作业1-fmt.Scanf()

package main

import (
	"bufio"
	"fmt"
	"math/rand"
	"os"
	"strconv"
	"strings"
	"time"
)

func main() {
	maxNum := 100
	rand.Seed(time.Now().UnixNano())
	secretNumber := rand.Intn(maxNum)
	//fmt.Println("The secret number is ", secretNumber)
	for {
		fmt.Println("input an integer number please:")
		reader := bufio.NewReader(os.Stdin)
		input, err := reader.ReadString('\n')
		if err != nil {
			fmt.Println("An error occured while reading input.Please try again", err)
			continue
		}
		input = strings.TrimSuffix(input, "\n")
		guess, err := strconv.Atoi(input)
		if err != nil {
			fmt.Println("Invalid input.Please enter an integer value")
			continue
		}
		// fmt.Println("your guess number is", guess)
		if guess > secretNumber {
			fmt.Println("your guess number is bigger than secreteNumber")
		} else if guess < secretNumber {
			fmt.Println("your guess number is smaller than secreteNumber")
		} else {
			fmt.Println("Correct!")
			break
		}
	}

}
package main

import (
	"fmt"
	"math/rand"
	"time"
)

func main() {
	// 定义guess变量
	var guess int
	maxNum := 100
	rand.Seed(time.Now().UnixNano())
	secretNumber := rand.Intn(maxNum)
	//fmt.Println("The secret number is ", secretNumber)
	for {
		fmt.Println("input an integer number please:")
        // Scanf函数
		fmt.Scanf("%d", &guess)
		if guess > secretNumber {
			fmt.Println("your guess number is bigger than secreteNumber")
		} else if guess < secretNumber {
			fmt.Println("your guess number is smaller than secreteNumber")
		} else {
			fmt.Println("Correct!")
			break
		}
	}

}