这是我参与「第五届青训营 」伴学笔记创作活动的第1天
变量
- 定义变量
// 显示声明
var str1 string = "hello go!"
// 关键字 变量名 变量类型=变量值
// 隐式声明
str2 := "hello go twice!"
- 引用一个包
- 一个文件夹里不能出现多个包,即只能有一个包。但是一个文件夹可以有多个文件,多个文件可以使用同一包名,但要注意变量不能冲突。
- 包里只有大写的变量和函数才能被其他包引用,即大写的是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)
- 数据类型
常用的:
-
- unit
- int
- float64
- bool
fmt.Printf("%T",num) 打印num的数据类型。
- 数据类型的转换
-
- string -> int
int, err := strconv.Atoi(string) - string -> int64
int64, err := strconv.ParseInt(string,10,64) - int -> string
string := strconv.Itoa(int) - int64 -> string
string := strconv.FormatInt(int64,10) - 字符串到float32/float64
float32, err = ParseFloat(string,32)floast64, err = ParseFloat(string, 64)
- string -> int
- 复杂数据类型
结构(struct),接口(interface),数组[数组长度] 值类型{值1, 值2},切片(slice) []值类型{值1,值2} ,map [key类型]值类型{key:值},指针 *,函数 func,管道 chan
控制语句
- 递增递减语句
自增++ 自减 --
- if-else
和C++/java的使用方法一样
if(){
}else{
}
// 多分支
if(){
}else if(){
}else if(){
}else{
}
- 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")
}
- 循环
// 死循环
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}
}
- 切片
不固定长度的数组。和python列表的slice一样。(好吧,打脸了,还是有区别的。)
Go的切片的值修改会影响原来的数组,python不会。
python的切片是浅拷贝,但是只有嵌套的列表值修改才会影响原来的值。Go的slcie是浅拷贝
更多关于Go的复制可阅读:
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
}
}
}