GO语言基础
认识并安装GO语言开发环境
Go语言简介
- Go语言是谷歌2009年发布的第二款开源编程语言
- go语言专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++代码的速度,而且更加安全,支持并行进程
Go语言特点
- 简洁、快速、安全
- 并行、有趣、开源
- 内存管理,数组安全,编译迅速
Go语言开发的应用
- docker
- Codis(豆瓣开发的大部分使用go语言)
- Glow类似于hadoop
- cockroach
一些见解
- Java语言的份额继续下滑,并最终被C和Go语言超越;
- C语言将长居编程榜第二的位置,并有望在Go取代java前重获语言榜第一的宝座
- Go语言最终会取代java,居于编程榜之首
Go语言环境搭建
- go源码安装
- go标准包安装
- 第三方工具安装 比如GVM
- go语言开发工具
- LiteIDE
- IDE
- eclipese、sublime
GO语言基础知识
第一个Go应用HelloWord
-
package main import "fmt" func main(){ //go语言不强制加分号 fmt.Print("Hello word") } //cmd输入 go run hello.go输出结果
配置
- go语言依赖一个重要得环境变量:$GOPATH(不是安装目录)
- 使用go get github.com/astaxie/beego命令下载框架失败,是因为未配置gopath
- set GOPATH=e:/go_path:设置gopath路径
- echo %GOPATH%:查看gopath路径
- gopath得作用
- 下载第三方代码
- 包管理与引用
- gopath多个包调用代码练习
Go语言常用关键字
- break default func interface select case defer go map struct chan else goto package switch const fallthrough if range type continue for import return var
- package main下得main()函数是go语言得入口
- var:关键字是go最基本得定义变量的方式,与C语言不同的是Go把变量类型放在变量名后面
- 例:var x int
Go语言开发工具liteide
-
创建应用编译
-
y:=“hello” //简短声明的使用,可定义多个
-
代码:
-
package main import "fmt" func main() { var x int x = 1 //这种用法须在函数体内 y, z := "go demo", 2 fmt.Printf("%d %s %d", x, y, z) }
-
go语言数据类型
- bool
- runne
- int8、int16、int32、int64
- byte
- unit8、unit16、unit32、unit64
- flot32、float64
- complex64、complex128
- string
- array slice
- map
其它基础
-
数组的定义
-
其它数据类型的使用
-
s:=make([]int,10,20)//slice动态数组对象
-
map:student:=make(map[string]int)
- make用于内建类型(map、slice、channel)的内存分配
-
流程控制语句
-
if语句
-
for
-
func main() { sum := 0 x := 1 for x <= 100 { sum += x x++ } fmt.Print(sum) }
-
-
switch
-
x:=1 switch x{ case 1: fmt.Print("demo1") //GO默认添加了break break case 2: //继续需要添加 fallthrough case 3: fmt.Print("demo2") break default 3: fmt.Print("demo3") }
-
-
for循环
-
x := [5]int{1, 2, 3, 4, 5} for i, v := range x { fmt.Println(i, v) } x := make(map[string]int) x["zhangsan"] = 78 x["lisi"] = 90 x["wangwu"] = 100 for i, v := range x { fmt.Println(i, v) } x := "zhangsan" for _, v := range x { fmt.Printf("%c\n", v) }
-
-
-
Go语言函数
-
func funcName(input1 type1,input2 type2)(output1 type1,output2 type2){ //逻辑处理代码 //返回多个值 return value1,value2 } package main import "fmt" func swap(a int, b int) (int, n int) { return b, a } func main() { a := 1 b := 2 a, b = swap(a, b) fmt.Printf("%d %d", a, b) } //匿名函数 f:=func(x,y int)int{ return x+y } fmt.Println(f(2,3))
-
go语言中指针的概念
-
defer关键词使执行顺序倒着走,退出或资源关闭时使用
-
defer func() { fmt.Println("After defer") }() fmt.Println("befor defer") //defer语句遇到异常继续执行
-
-
-
Go语言结构struct
-
package main import "fmt" type Person struct { name string age int } type Student struct{ Person//匿名字段,使用和类包含类似 speciality string } func main() { person := Person{"zhangsan", 25} // person2 :=Person{age:25,name:"wangwu"}//指定字段赋值 fmt.Printf("%v", person) }
-
GO语言面向对象
类的定义与使用
-
简单定义使用
-
package main import "fmt" type Integer struct { value int } func (a Integer) compare(b Integer) bool { return a.value < b.value } func main() { // var a int =1 // var b int =2 a := Integer{1} b := Integer{2} fmt.Printf("%v", a.compare(b)) }
-
-
go中类的初始化
-
point:=new(Point) point:=&Point{} point:=&Point{x:100,y:100} point:=Point{}
-
定义与使用示例
-
package main import "fmt" type Point struct { px float32 py float32 } func (point *Point) setxy(px, py float32) { point.px = px point.py = py } func (point *Point) getxy() (float32, float32) { return point.px, point.py } func main() { point := new(Point) point.setxy(1.24, 4.25) px, py := point.getxy() fmt.Print(px, py) }
-
-
类的继承与使用
-
package main import "fmt" type Person struct { name string age int } func (person Person) getNameAndAge() (string, int) { return person.name, person.age } type Student struct { Person speciality string } func (student Student) getSpeciality() string { return student.speciality } func main() { student := new(Student) student.name = "zhangsan" student.age = 26 name, age := student.getNameAndAge() fmt.Println(name, age) }
-
Go语言接口
-
在go语言中,一个类只需要实现了接口要求的所有函数,我们就说这个类实现了该接口
-
package main import "fmt" //非侵入式接口 type Animal interface { Fly() Run() } type Animal2 interface { Fly() } type Bird struct { } func (bird Bird) Fly() { fmt.Println("bird is flying") } func (bird Bird) Run() { fmt.Println("bird is Run") } func main() { var animal Animal var animal2 Animal2 bird := new(Bird) animal = bird animal2=bird animal2.FLy() animal2=animal//在GO中可以接口赋值 animal.Fly() animal.Run() }
-
-
在Go语言中空间口类似泛型
-
var v1=interface{} v1=6.78 fmt.Print(v1) //类型查询,看接口接收的什么类型 if v, ok := v1.(float64); ok { fmt.Println(v, ok) }
-
-
GO语言进阶
GO语言并发编程
Go语言并发编程之协程
-
与传统的系统级线程相比,协程的大优势在于其"轻量级",可以轻松创建上百万个而不会导致系统资源衰竭,而线程和进程通常多也不能超过1万个,这也是协程也叫轻量级线程的原因.
-
go对协程的实现:go+函数名:启动一个协程执行函数体
-
package main import ( "fmt" "time" ) func test_Routine() { fmt.Println("This is one routine!") } func main() { go test_Routine() time.Sleep(1) }
-
-
Go并发编程之channel
-
Channel:Go语言在语言级别提供的goroutine间的通讯方式
-
声明方式:var chanName chan ElementType
-
package main import ( "fmt" "strconv" ) func Add(x, y int, quit chan int) { z := x + y fmt.Println(z) quit <- 1 } func Read(ch chan int) { value := <-ch fmt.Println("value:" + strconv.Itoa(value)) } func Write(ch chan int) { // ch < -10 } func main() { chs := make([]chan int, 10) for i := 0; i < 10; i++ { chs[i] = make(chan int) go Add(i, i, chs[i]) } for _, v := range chs { <-v } }
-
-
-
缓存channel
-
package main import ( "fmt" "time" ) var ch chan int func test_channel() { // ch := make(chan int) ch <- 1 fmt.Println("come to end goroutline 1") } func main() { ch = make(chan int, 2) //值是1和值是0的适合输出执行顺序不同 go test_channel() time.Sleep(2 * time.Second) fmt.Println("running end!") <-ch time.Sleep(time.Second) }
-
-
select
-
是linux很早就引入的函数,用来实现非阻塞的一种方式
-
go语言提供语言级别支持slelect关键字,用于处理异步IO问题
-
select{ case <-chan1://如果chan1成功读取到数据,则进行该case处理语句 case chan2 <-1://如果成功向chan2写入数据,则进行该case处理 default: //如果上面都没有成功,则进入default处理流程 }
-
-
select 三个代码示例
-
示例1
package main import ( "fmt" "time" ) func main() { ch := make(chan int) go func(ch chan int) { ch <- 1 }(ch) // time.Sleep(2)//加这一句执行结果不同 select { case <-ch: fmt.Print("come to read ch!") default: fmt.Print("come to default!") } }
-
示例2
package main //超时控制的经典实现 import ( "fmt" "time" ) func main() { ch := make(chan int) timeout := make(chan int, 1) go func() { time.Sleep(time.Second) timeout <- 1 }() select { case <-ch: fmt.Println("come to read ch!") case <-timeout: fmt.Println("come to timeout") } fmt.Print("end of code!") }
-
示例3
package main //超时控制的经典实现 import ( "fmt" "time" ) func main() { ch := make(chan int) select { case <-ch: fmt.Println("come to read ch!") case <-time.After(time.Second): fmt.Println("come to timeout") } fmt.Print("end of code!") }
-
-
-
-
深入Go协程编程
-
协程与线程质的不同
- 协程任务的业务代码主动要求切换,即主动让出执行权
- 发生了IO,导致执行阻塞
-
线程与协程代码对比(线程几百个就卡,协程十万个都不算多)
-
Java线程
public class MyThread{ public static void main(String[] args){ new Thread(new Test_thread()).start(); new Thread(new Test_thread2()).start() } } class Test_thread implements Runnable{ public void run(){ for(int i=0;i<100;i++){ System.out.println("thread 1:"+i) } } } class Test_thread2 implements Runnable{ public void run(){ for(int i=100;i<200;i++){ System.out.println("thread 2:+i); } } }
-
Go协程
package main import ( "fmt" // "runtime" "strconv" "time" ) func main() { //协程1 go func() { for i := 1; i < 100; i++ { if i == 10 { // runtime.Gosched() //主动要求切换CPU <-ch //遇到阻塞主动让出,否则一直执行下去 } fmt.Println("routine 1:" + strconv.Itoa(i)) } }() //协程2 go func() { for i := 100; i < 200; i++ { fmt.Println("routine 2:" + strconv.Itoa(i)) } }() time.Sleep(time.Second) }
-
-
GO语言JSON与MD5
Go语言的JSON
-
使用的库
- Go语言内置的encoding/json标准库:性能不太好
- github.com/pquerna/ffjson/ffjson
-
json使用代码
package main import ( "encoding/json" "fmt" ) type Student struct { Name string //外部要引用要首字母大写 Age int } func main() { //对数组类型的json编码 x := [5]int{1, 2, 3, 4, 5} s, err := json.Marshal(x) if err != nil { panic(err) } fmt.Println(string(s)) //对map类型进行json编码 m := make(map[string]float64) m["zhangsan"] = 100.4 s2, err2 := json.Marshal(m) if err2 != nil { panic(err2) } fmt.Println(string(s2)) //对对象进行json编码 student := Student{"zhangsan", 26} s3, err3 := json.Marshal(student) if err3 != nil { panic(s3) } fmt.Println(string(s3)) //对s3进行解码 var s4 interface{} json.Unmarshal([]byte(s3), &s4) fmt.Printf("%v", s4) }
-
md5使用
package main import ( "crypto/md5" "fmt" ) func main() { Md5Inst := md5.New() Md5Inst.Write([]byte("zhangsan")) Result := Md5Inst.Sum([]byte("")) fmt.Printf("%x\n\n", Result) }
GO语言HTTP
-
go语言标准库内建提供了net/http包
-
处理http请求:使用net/http包提供的http.ListenAndServer()方法,可以在指定的地址进行监听,开启一个HTTP.服务端该方法的原型如下:func ListenAndServe(addr string,hander Handler)error
- 该方法用于在指定的TCP网络地址addr进行监听,然后调用服务端处理程序来处理传入的链接请求.该方法有两个参数:第一个参数addr即监听地址;第二个服务表示服务端处理程序,通常为空,这意味着服务端调用http.DefaultServeMux进行处理,而服务端编写的业务逻辑处理程序http.Handle()或http.HandleFunc()默认注入http.DefaultServeMux中
-
处理https请求
- func ListenAndServeTLS(addr string,certFile string,keyFile string,handler Handler) error
- http.HandleFunc()方法接受两个参数
- 第一个参数是http请求的目标路径"/hello",该参数值可以是字符串,也可以是字符串形式的正则表达式,第二个参数指定具体的回调方法,比如helloHandler
- 当我们的程序运行起来后,访问-http://localhost:8080/hello,程序就会去调用hellloHandler()方法中的业务逻辑程序
-
http中get和postdaima
-
//get代码 package main import ( "fmt" "io/ioutil" "net/http" ) func main() { resp, err := http.Get("http://www.baidu.com") if err != nil { panic(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } //post代码 package main import ( "fmt" "io/ioutil" "net/http" "strings" ) func main() { resp, err := http.Post("http://www.baidu.com", "application/x-www.form-urlencoded", strings.NewReader("id=1")) if err != nil { panic(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) }
-
GO语言正则表达式
Go语言标准库内建提供了regexp包
-
正则字母含义
- .匹配除换行符以外的任意字符
- \w匹配字母或数字或下划线或汉字
- \s匹配任意的空白符
- \d匹配数字
- \b匹配单词的开始或结束
- ^匹配字符串的开始
- $匹配字符串的结束
- *重复零次或更多次
- +重复一次或更多次
- ?重复零次或一次
- {n}重复n次
- {n,}重复n次或更多次
- {n,m}重复n到m次
- 捕获(exp) 匹配exp,并捕获文本到自动命名的阻组里
- (?exp) 匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name’exp)
- (?:exp)匹配exp,不捕获匹配的文本,也不给此分组分配组号
-
正则函数
- func Match(pattern string,b []byte)(matched bool,err error)
- func MatchString(pattern string,s string)(matched bool,err error)
- func MustCompile(str string)*Regexp
- func(re * Regexp)FindAllString(s string,n int)[]string
-
代码演示
-
package main import ( "fmt" "regexp" ) func main() { isok, _ := regexp.Match("[a-zA-Z]{3}", []byte("zhl")) fmt.Printf("%v", isok) reg1 := regexp.MustCompile(`^z(.*)l$`) result1 := reg1.FindAllString("zhangsan", -1) fmt.Printf("%v\n", result1) reg2 := regexp.MustCompile(`z(.{1})(.{1})(.*)l$`) result2 := reg2.FindAllStringSubmatch("zhangsan", -1) fmt.Printf("%v\n", result2) }
-
代码演示2
package main import ( "fmt" "io/ioutil" "net/http" "regexp" ) func main() { url := "https://movie.douban.com/subject/1292052/" resp, err := http.Get(url) if err != nil { panic(err) } defer resp.Body.Close() sHtml, _ := ioutil.ReadAll(resp.Body) // fmt.Println(string(sHtml)) reg := regexp.MustCompile(`<span\s*property="v:itemreviewed">(.*)</span>`) result := reg.FindAllStringSubmatch(string(sHtml), -1) // fmt.Printf("%v", result) // for _, v := range result { // fmt.Println(v[1]) // } fmt.Println(result[0][1]) reg1 := regexp.MustCompile(`<strong\s*class="ll\s*rating_num"\s*property="v:average">(.*)</strong>`) result1 := reg1.FindAllStringSubmatch(string(sHtml), -1) fmt.Println(result1[0][1]) }
-
GO语言Mysql与Redis
Go语言使用mysql驱动包:https://github.com/Go-SQL-Driver/Mysql
-
使用sql.open()函数用来打开一个注册过的数据库驱动,Go-MySQL-Driver中注册了mysql这个数据库的驱动,第二个参数是DNS(Data Source Name),它是Go-MySQL-Driver定义的一些数据库链接和配置信息.它支持如下格式
- user@unix(/path/to/socket)/dbname?charset=utf8
- user:password@tcp(localhost:5555)/dbname?chaset=utf8
-
Go语言操作mysql代码
-
package main import ( "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" ) func main() { db, err := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/cost?charset=utf8") if err != nil { panic(err) } //插入 // stmt, err := db.Prepare("insert test set t_id=?,t_name=?,t_time=?") // res, err := stmt.Exec(998, "zhangsan", "2019-01-02") // id, err := res.LastInsertId() //修改 // stmt, err := db.Prepare("update test set t_name=? where t_id=?") // res, err := stmt.Exec("lisi", 999) // id, err := res.RowsAffected() //数据库一主多从,从库多是用来查询的 //查询 rows, err := db.Query("select * from test where t_id=999") if err != nil { panic(err) } for rows.Next() { var t_id int var t_name string var t_time string err = rows.Scan(&t_id, &t_name, &t_time) fmt.Println(t_id, t_name, t_time) } //在go中创建的变量必须调用一次 // fmt.Println(id) }
-
Go语言使用的Redis驱动包:https://github.com/astaxie/goredis
-
驱动包需设置gopath下载使用
-
redis的基本操作类型
- string
- hash
- set
- list
- zset
-
redis代码示例
package main import ( "fmt" "github.com/astaxie/goredis" ) func main() { var client goredis.Client client.Addr = "127.0.0.1:6379" //存入数据到redis err := client.Set("test", []byte("hello beifeng")) if err != nil { panic(err) } //从redis获取数据 res, err := client.Get("test") if err != nil { panic(err) } fmt.Println(string(res)) //库中hmset方法使用 f := make(map[string]interface{}) f["name"] = "zhangsan" f["age"] = 12 f["sex"] = "male" err = client.Hmset("test_hash", f) if err != nil { panic(err) } //库中 zset方法使用 _, err = client.Zadd("test_zset", []byte("beifeng"), 100) if err != nil { panic(err) } }
-
redis命令行操作查看
-
//启动服务 redis-server.exe //启动客户端查看数据 E:\quickSorftWare\redis>redis-cli.exe 127.0.0.1:6379> get test "hello golang" 127.0.0.1:6379> type test_hash none 127.0.0.1:6379> type test_hash hash 127.0.0.1:6379> hgetall test_hash 1) "age" 2) "12" 3) "sex" 4) "male" 5) "name" 6) "zhangsan" 127.0.0.1:6379> hgetall test_zadd (empty list or set) 127.0.0.1:6379> type test_zadd none 127.0.0.1:6379> type test_zset zset 127.0.0.1:6379> zrange test_zset 0 -1 1) "golang"
-