黑马GO语言 ---- 学习笔记
Go语言
- 文件入口main
- 左括号必须同行
- 每个文件必须先声明包(必须得有main包)
- 没有分号
- 导包必须得用
数据类型
变量的声明 ==> var a int
c := 10 自动推导类型
多重赋值 a,b := 10, 20 互换 a, b := b, a
匿名变量 _, b, _ = func() 配合函数返回值使用
var (
a int = 1
b float64 = 1.0
)
**常量 **
const a int = 10 const a = 10
const (
a = 1
b = 1.1
)
iota枚举 常量自动生成器 但是遇到const会变成0
package main
import "fmt"
func main() {
const (
a = iota
b = iota
c = iota
)
fmt.Printf("a = %d, b = %d, c = %d", a, b, c)
const d = iota
fmt.Printf("d = %d", d)
const (
i = iota
j, k = iota, iota // 同一行值一样
h = iota
)
fmt.Printf("i = %d, j = %d, h = %d", i, j, h)
}
switch
package main
import "fmt"
func main() {
fmt.Println("请数入:")
var a int
fmt.Scan(&a)
switch a := 1;a {
case 1:
fmt.Println("111")
fallthrough //不加默认跳出
case 2:
fmt.Println("222")
fallthrough
case 3:
fmt.Println("333")
default
fmt.Println("444")
}
}
switch {
case a > 10:
fmt.Println("111")
fallthrough //不加默认跳出
case a < 10:
fmt.Println("222")
fallthrough
case a == 10:
fmt.Println("333")
default
fmt.Println("444")
}
循环
package main
import "fmt"
func main() {
sum := 0
for i := 1; i <= 100; i++ {
sum = sum + i
}
fmt.Println("sum = ", sum)
}
package main
import "fmt"
func main() {
str := "abc"
for i, data := range str {
fmt.Printf("str[%d] = %c\n", i, data)
}
for i := range str {
fmt.Printf("str[%d] = %c\n", i, str[i])
}
}
跳转
goto 不能跨函数
package main
import "fmt"
func main() {
fmt.Println("111111")
goto End
fmt.Println("222")
End:
fmt.Println("333333")
}
函数
package main
import "fmt"
// 无参无返回值
func MyFunc() {
a := 666
fmt.Println("a = ", a)
}
// 有参无返回值
func MyFunc01(a int) {
fmt.Println("a = ", a)
}
// 不定参数类型 必须放在最后
func MyFunc02(a int, args ...int) {
fmt.Println("len", len(args))
MyFunc03(args[1:]...)
}
func MyFunc03(args ...int) {
for _, data := range args {
fmt.Println(data)
}
}
// 有返回值
func MyFunc04() (result int) {
result = 777
return
}
func MyFunc05() (a int, b int, c int) {
a, b, c = 11, 22, 33
return
}
func main() {
a, b, c := MyFunc05()
fmt.Println("c = ", a, b, c)
}
有参有返回值
递归函数
pakeage main
import "fmt"
func test01() (sum int) {
if (i == 1) {
return 1
}
return i + test01(i - 1)
}
func main() {
var sum int
sum = test01(100)
fmt.Println("sun = ", sum)
}
函数类型
pakeage main
import "fmt"
func add(a, b, int) int {
return a + b
}
func bdd(a, b, int) int {
return a - b
}
type FuncType func(int, int) int
func main() {
var ftest FuncType
ftest = add
result := ftest(10, 20)
}
回调函数(函数参数有函数类型) (多态)
pakeage main
import "fmt"
// 实现加法
func add(a, b, int) int {
return a + b
}
// 实现减法
func bdd(a, b, int) int {
return a - b
}
type FuncType func(int, int) int
func calc(a, b, int, ftest FuncType) (result int) {
Println("calc")
result = ftest(a, b)
return
}
func main() {
a := calc(1, 1, add)
fmt.Println("a = ", a)
b := calc(1, 1, bdd)
fmt.Println("b = ", b)
}
闭包 (匿名函数)
func main() {
a := 10
str := "mike"
f1 := func() {
fmt.Println("a = ", a)
fmt.Printlb("str =", str)
}
f1()
type FuncType func()
var f2 func()
f2 = f1
func () {
fmt.Println("111")
} ()
func (i, j int) (max int) {
if i > j {
max = i
}
return
} (10, 20)
}
闭包引用方式捕获外部变量 (闭包是自己独立的空间,里面变量不会释放)
defer(析构) 延迟调用
func main() {
defer fmt.Println("bbbb")
fmt.Println("aaaaaa")
}
调用顺序 (后进先出) 函数发生错误也会执行
和闭包一起使用
func main() {
a := 10
b := 20
defer func(a, b, int) {
fmt.Printf("a = %d, b = %d\n", a, b)
}(a, b) //已经先传参了
a = 111
b = 222
fmt.Println("a ,b", a, b)
}
获取命名行参数
package main
import "fmt"
import "os"
func main() {
list := os.Args
n := len(list)
fmt.Println("n = ", n)
}
工程管理
src源文件, gopath gobin设置
package main
import print "fmt" //必须使用
import _ "os" //忽略 需要使用 init函数
func main() {
n := 6
print.Println("n = ", n)
}
init函数 到包先执行
// 为了执行init函数
import (
_ "fmt"
)
复合类型
指针
package main
import "fmt"
func main() {
var a int = 10
var p *int = &a
fmt.Println("%v", p)
}
---------------------
package main
import "fmt"
func swap(p1, p2 *int) {
*p1, *p2 = *p2, *p1
}
func main() {
a, b := 10, 20
swap(&a, &b)
fmt.Println("a b", a, b)
}
new函数 自动回收
package main
import "fmt"
func main() {
var p *int
p = new(int)
*p = 666
fmt.Println("p = ", *p)
}
数组
package main
import "fmt"
func main() {
var id [50]int //元素个数是常量
c := [5]int{1,2,3}
b := [5]int{2:10, 4:20}
// 比较(== OR !=)和赋值
fmt.Println("a b", id[0], id[1])
}
-----------
//随机数
package main
import "fmt"
import "math/rand"
import "time"
func main() {
rand.Seed(time.Now().UnixNano())
for i := 0; i < 5; i++ {
fmt.Println("rand = ", rand.Intn(100))
}
}
切片(动态数组)
slice
package main
import "fmt"
func main() {
a := []int{1, 2, 3, 0, 0}
s := a[1:3:5]
fmt.Println("s=", s)
fmt.Println("s=", len(s))
fmt.Println("s=", cap(s))
}
--------------
// 和数组的区别,容量和长度不固定 切片出来的数据会改变原始数据
package main
import "fmt"
func main() {
s := []int{}
// s2 := make([]int, 5, 10)
// s3 := make([]int, 5) 长度和容量一样为5
fmt.Println("len(s),cap(s)", len(s), cap(s))
s = append(s, 11)
fmt.Println("len(s),cap(s)", len(s), cap(s))
}
---------------
// 切片操作
package main
import "fmt"
func main() {
array := []int{0, 1, 2, 3}
s1 := array[:]
data := array[1]
s2 := array[2:3:4]
s3 := array[:4]
s3 := array[2:]
// copy
}
------------
//引用传递
map
package main
import "fmt"
func main() {
var m1 map[int]string
m2 := make(map[int]string, 10)
m2[1] = "make"
for key,value := m1 {
}
delete(m2, 1)
test(m1) //引用传递
}
结构体
使用其他包的函数,结构体,首字母必须大写
是有的话就小写
package main
import "fmt"
type Student struct {
id int
name string
sex byte
age int
addr string
}
func main() {
// 顺序初始化必须全部
var s1 Student = Student{1, "make", 'm', 18, "bj"}
fmt.Println("s1 = ", s1)
s2 := Student{name: "make"}
s2.name = "mike"
p2 := &Student{name: "mike"}
fmt.Println("p2 = ", *p2)
p2.name = "mike" // 没有->
}
面向对象编程
继承
匿名字段
package main
import "fmt"
type Student struct {
name string
age int
}
type People struct {
foot int
head int
name string //同名复写
Student
*Student // 初始化多加 &
}
func main() {
var p1 People = People{2, 1, Student{"mike", 10}}
fmt.Println("p1.name", p1.name, p1.age)
p1.Student.name = "mike"
p2 := People{Student: Student{name: "mike"}}
fmt.Println("p1.name", p2)
}
-------------------------
// 继承
package main
import "fmt"
type Person struct {
name string
sex byte
age int
}
func (tmp *Person) PrintInfo() {
fmt.Println("tmp = ", *tmp)
}
type Student struct {
Person
id int
addr string
}
func (tmp *Student) PrintInfo() {
fmt.Println("tmp = ", *tmp)
}
func main() {
s := Student{Person{"mike", 'm', 18}, 1, "bj"}
s.PrintInfo()
sfunc := s.PrintInfo //方法值
sfunc()
f := (*person).PrintInfo()
f(&s)
}
封装
方法
package main
import "fmt"
func Add(a, b int) int {
return a + b
}
type long int
// tmp 是接收者 接收者本身不能是指针 接收者类型不同函数名可以一样
func (tmp long) Add01(other long) long {
return tmp + other
}
type long32 long
func (tmp long32) Add01(other long) long {
return tmp + other
}
func main() {
var result int
result = Add(1, 1)
fmt.Println("result = ", result)
var a long = 2 // 接收者就是对象
r := a.Add01(3)
fmt.Println("result = ", r)
}
------------------------
package main
import "fmt"
type Person struct {
name string
sex byte
age int
}
func (tmp Person) testprint() {
fmt.Println("tmp = ", tmp)
}
func (p *Person) setinfo(n string, s byte, a int) {
p.name = n
p.sex = s
p.age = a
}
func main() {
p := Person{"mike", 'm', 18}
p.testprint()
var p2 Person //对象
(&p2).setinfo("yoyo", 'f', 22) // 引用传递
p2.testprint()
}
----------------
// 指针变量的方法集
func main() {
p := &Person{"mike", 'm', 18}
p.setinfo("yoyo", 'f', 22) //内部会自动转换
(*p).set("yoyo", 'f', 22)
p2.testprint()
}
接口
定义接口
package main
import "fmt"
//定义接口类型
type Humaner interface {
sayhi()
}
type Student struct {
name string
id int
}
func (tmp *Student) sayhi() {
fmt.Println("学生")
}
type Teacher struct {
addr string
group string
}
func (tmp *Teacher) sayhi() {
fmt.Println("老师")
}
func WhoSayhi(i Humaner) {
i.sayhi()
}
func main() {
/*var i Humaner
s := &Student{"mike", 19}
i = s
i.sayhi()
t := &Teacher{"mike", "go"}
i = t
t.sayhi()
*/
s := &Student{"mike", 19}
t := &Teacher{"mike", "go"}
WhoSayhi(s)
WhoSayhi(t)
}
----------------
//接口的继承
package main
import "fmt"
//定义接口类型
type Humaner interface {
sayhi()
}
type Personer interface {
Humaner
sing(lrc string)
}
type Student struct {
name string
id int
}
func (tmp *Student) sayhi() {
fmt.Println("学生")
}
func (tmp *Student) sing(lrc string) {
fmt.Println("学生", lrc)
}
func main() {
var i Personer
s := &Student{"mike", 55}
i = s
i.sayhi()
i.sing("111")
//接口转换 父类可以接收子类
var ipro Personer
ipro = &Student{"mike", 77}
var base Humaner
base = ipro
base.sayhi()
}
---------------------------
// 空接口
package main
import "fmt"
type Student struct {
name string
id int
}
func main() {
//万能类型 void *
//var i1 interface{} = 1
//fmt.Println("i = ", i1)
//类型断言
i := make([]interface{}, 3)
i[0] = 1
i[1] = "go"
i[2] = Student{"mike", 666}
for _, data := range i {
if _, ok := data.(int); ok == true {
fmt.Println("int")
} else if _, ok := data.(string); ok == true {
fmt.Println("string")
} else {
fmt.Println("struct")
}
}
}
异常处理
常用于返回错误
package main
import "fmt"
import "errors"
func MyDiv(a, b int) (result int, err error) {
err = nil
if b == 0 {
err = errors.New("分母不能为零")
} else {
result = a / b
}
return
}
func main() {
//err1 := fmt.Errorf("%s", "thisis normol err1")
//fmt.Println("err1 = ", err1)
//err2 := errors.New("this is normal err2")
//fmt.Println("err2", err2)
result, err := MyDiv(10, 0)
if err != nil {
fmt.Println("err = ", err)
} else {
fmt.Println("result =", result)
}
}
--------------------
// 致命错误
package main
import "fmt"
func testa() {
fmt.Println("aaaaaaaa")
}
func testb(x int) {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
}()
var a [10]int
a[x] = 111 //默认会调用
//panic("this is a panic test")
}
func testc() {
fmt.Println("ccccccccccc")
}
func main() {
testa()
testb(20)
testc()
}
字符串操作
package main
import (
"fmt"
"strings"
)
func main() {
// "hellogo" 是否有”hello"
fmt.Println(strings.Contains("hellogo", "hello"))
// joins 组合
s := []string{"abc", "hello", "mike"}
buf := strings.Join(s, "x")
fmt.Println("buf = ", buf)
// index
fmt.Println(strings.Index("abc", "cd"))
buf = strings.Repeat("go", 3)
fmt.Println("buf = ", buf)
// Split
buf = "hello@go@mike"
s2 := strings.Split(buf, "@")
//trim
strings.Trim(" are y ok ", " ")
//Fields
s3 := strings.Fields(" are y ok ")
}
----------------------
//字符串转换
package main
import (
"fmt"
"strconv"
)
func main() {
slice := make([]byte, 0, 1024)
slice = strconv.AppendBool(slice, true)
slice = strconv.AppendInt(slice, 123, 10)
slice = strconv.AppendQuote(slice, "abc")
fmt.Println("slice = ", string(slice))
var str string
str = strconv.FormatBool(false)
str = strconv.FormatFloat(3.14, 'f', -1, 64)
fmt.Println("str = ", str)
str = strconv.Itoa(6666)
fmt.Println("str = ", str)
a, _ := strconv.Atoi("56654")
}
正则表达式
package main
import (
"fmt"
"regexp"
)
func main() {
buf := "abc azc a7c aac 888";
// 解释规则
reg1 := regexp.MustComplile(`a.c`)//a[0-9]c
if reg1 == nil {
fmt.Println("err")
return
}
// 提取信息
result := reg1.FindAllStringSubmatch(buf, -1)// -1表示全部
fmt.Println("result = ", result)
}
---------------------
package main
import (
"fmt"
"regexp"
)
func main() {
buf := "3.14 567 asd 1.23 7. 8.99 llk1 6.66"
reg := regexp.MustCompile('\d+\.\d+')
if ret == nil {
fmt.Println("err")
return
}
//result := reg.FindAllString(buf, -1)
result := reg.FindAllStringSubmatch(buf, -1)//分组
fmt.Println("result =", result)
}
------------------------
// 爬虫
package main
import (
"fmt"
"regexp"
)
func main() {
buf := `网页信息` //原生字符串
reg := regexp.MustCompile('<div>(?s:(.*?))</div>')
if ret == nil {
fmt.Println("err")
return
}
//result := reg.FindAllString(buf, -1)
result := reg.FindAllStringSubmatch(buf, -1)//分组
fmt.Println("result =", result)
// 过滤
for _, text := range result {
fmt.Println("text[0] = ", text[0])
fmt.Println("text[1] = ", text[1])
}
}
json
编码和解码
package main
import (
"fmt"
"encoding/json"
)
//成员变量名必须大写
type IT struct {
Company string
Subject []string
IsOk bool
Price float64
}
/* 二次编码
type IT struct {
Company string `json:"-"`
Subject []string `json:"subjects"`
IsOk bool `json:",string"`
Price float64
}
*/
func main() {
s := IT{"IT", []string{"go", "c", "c++"}, true, 666.666}
//buf, err := json.Marshal(s)
//格式化编码
buf, err := json.MarshalIndent(s, "", " ")
if err != nil {
fmt.Println("err = ", err)
return
}
fmt.Println("buf = ", string(buf))
//解析
jsonBuf := `json字符串`
var tmp IT
// 第二个参数地址传递
err := json.Unmarshal([]byte(jsonBuf), &tmp)
if err != nil {
fmt.Println("err = ", err)
return
}
fmt.Println("tmp = ", tmp)
type IT1 struct {
Subject []string `json:"subjects"`
}
var Tmp2 IT1
// 第二个参数地址传递
err := json.Unmarshal([]byte(jsonBuf), &tmp2)
if err != nil {
fmt.Println("err = ", err)
return
}
}
------------------
//通过map生成json
package main
import (
"fmt"
"encoding/json"
)
func main() {
// 创建一个map
m := make(map[string]interface{}, 4)
m["company"] = "itcast"
m["subjects"] = []string{"go", "c++"}
m["isok"] = true
m["price"] = 666.666
result, err := json.Marshal(m)
if err != nil {
fmt.Println("err = ", err)
return
}
fmt.Println("result = ", string(result))
jsonBuf := `json字符串`
m := make(map[string]interface{}, 4)
// 第二个参数地址传递
err := json.Unmarshal([]byte(jsonBuf), &m)
if err != nil {
fmt.Println("err = ", err)
return
}
fmt.Println("m = ", m)
// 不能直接赋值
//var str string
//str = m['conmpany']
// 需要反推
var str string
for key, value := range m {
switch data := value.(type) {
case string:
str = data
case bool:
case float64:
}
}
}
文件操作
package main
import (
"fmt"
"OS"
"io"
"bufio"
)
func WriteFile(path string) {
//打开文件
f, err := os.Create(path)
if err != nil {
return
}
//关闭
defer f.close()
var buf string
for i := 0 i <10; i++ {
buf = fmt.Sprintf("i = $d\n", i)
f.WriteString(buf)
}
}
func ReadFile(path string) {
f, err := os.Open(path)
if err != nil {
return
}
defer f,close
r := bufio.NewReader(f)
//读取一行
r.ReadBytes('\n')
}
// 每次读取一行
func ReadFileLine(path string) {
f, err := os.Open(path)
if err != nil {
return
}
defer f,close
buf := make([]byte, 1024 * 2)
n, err := Read(buf)
if err != nil && err != io.EOF { //结尾
return
}
fmt.Println("buf = ", string(buf[:n]))
}
func main() {
//os.Stdout.Close()
//os.Stdout.WriteString("are y ok")
path = "./demo.txt"
WriteFile(path)
ReadFile(path)
}
拷贝文件案例
package main
import (
"fmt"
"OS"
"io"
)
func main() {
list := os.Args
if len(list) != 3 {
fmt.Println("err")
return
}
srcFileName := list[1]
dstFileName := list[2]
if srcFileName == dstFileName {
fmt.Println("err")
return
}
sf, err1 := os.Open(srcFileName)
if err1 != nil {
fmt.Println("err")
return
}
df, err 2 := os.Open(dstFileName)
if err2 != nil {
fmt.Println("err")
return
}
defer sf.Close()
defer df.Close()
buf := make([]byte, 4 * 1024)
for {
n, err := sf.Read(buf)
if err != nil {
if err == io.EOF {
break
}
fmt.Println("err")
}
df.Write(buf[:n])
}
}
go优势
并发(时间片轮转交替使用)和并行
语音层面上的并发,支持GC自动垃圾回收,通过通信的方法支持同步
goroutine
go协程,十几个goroutine可能底层就是5,6个线程,go语音实现了goroutine之间的共享内存
package main
import (
"fmt"
"time"
)
func newTask() {
for {
fmt.Println("this is new")
time.Sleep(time.Second)
}
}
// 主协程退出,子协程也退出
func main() {
go newTask() //新建一个协程
for {
fmt.Println("this is main")
time.Sleep(time.Second)
}
}
----------------------
// runtime 包 设置协程
package main
import (
"fmt"
"runtime"
)
func main() {
go func() {
for i:= 0; i <5; i++
{
// 终止协程,协程中的程序都结束了
runtime.Goexit()
// 设置cpu数量
n := runtime.GOMAXPEOCS(2)
fmt.Println("go")
}
} ()
for i:= 0; i < 2; i++ {
// 让出时间片
runtime.Goshed()
fmt.Println("this is main")
}
}
channel
通过管道实现通信,是一个数据类型
package main
import (
"fmt"
"runtime"
)
// 全局变量,创建channel
var ch = make(chan int)
func Printer(str string) {
for _, data := range str {
fmt.Printf("%c", data)
}
fmt.Printf("\n")
}
func person1() {
Printer("hello")
ch <- 666
}
func person2() {
<- ch //从管道取数据,接受,没数据会阻塞
Printer("world")
}
func main() {
go person1()
go person2()
for {
}
}
--------------------
// 数据交换
package main
import (
"fmt"
"runtime"
)
func main() {
ch := make(chan string)
go func () {
defer fmt.Println("son");
for i := 0; i < 2; i++ {
fmt.Pritln("i",i)
}
ch <- "我是子协程"
}()
str := <- ch
fmt.Println('str',str)
}
--------------
// 无缓冲 => 接受和发送没准备好会阻塞 make(chan type, 0)
// 有缓存 make(chan type, capacity) 满了会阻塞
// 关闭channel
close(ch);
for {
if num, ok := <-ch; ok == true {
} else {
}
}
// 遍历ch
for num := range ch {
fmt
}
// 单向
pakeage main()
func main() {
ch := make(chan int)
var writenCh chan<- int = ch
var readCh <-chan int = ch
writeCh <- 666
<- readCh
}
定时器
pakeage main()
import (
"fmt"
"time"
)
func main() {
timer := time.NewTimer(1 * time.Second)
// 一次
for {
<-time.C
fmt.Println("时间到")
}
}
--------------------
pakeage main()
import (
"fmt"
"time"
)
func main() {
timer := time.NewTimer(3 * time.Second)
go func() {
<-timer.C
fmt.Println("子协程可以打印了")
}
//重新设置
timer.Reset(1 * time.Second)
//停止
timer.Stop()
for {
}
}
-----------------------------
// ticker 周期
pakeage main()
import (
"fmt"
"time"
)
func main() {
ticker := time.NewTicker(1 * time.Second)
i := 0
for {
<-ticker.C
i++
fmt.Println("i = ",i)
}
}
select
监听channel
pakeage main
import (
"fmt"
)
func f1(ch chan<- int, quit <-chan bool) {
x, y := 1, 1
for {
select {
case ch <- x:
x, y := y, x +y
case flag := <- quit:
fmt.Println("exit")
return
case <-time.After(3 * time.Second)
}
}
}
func main() {
ch := make(chan int)
quit := make(chan bool)
go func() {
for i := 0; i < 8; i++{
num := <-ch
fmt.Println("num =", num)
}
quit<-true
}()
f1(ch, quit)
}
go语言学习笔记
这个几个类型得用make创建
语法歧义
函数的特点
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析