2.7.5
2.7.5.1 协议通信过程
应用层 hello
传输层(udp tcp) 源port 目的端口 hello
网络层(ip) 源ip 目的ip 源port 目的端口 hello
链路层(mac) 源mac 目的mac 源ip 目的ip 源port 目的端口 hello
2.7.5.2 tcp传输(服务端)
//传输端
func main() {
listener, err := net.Listen("tcp", "127.0.0.1:8000")
if err != nil {
fmt.Println("err = ", err)
return
}
defer listener.Close()
//阻塞等待用户连接
for {
conn, _ := listener.Accept()
//接受请求
buf := make([]byte, 1024)
n, _ := conn.Read(buf)
//buf[:n] n有多少打印多少 长度是1024所以不可以打印全部
fmt.Println("puf :", string(buf[:n]))
conn.Close()
}
}
2.7.5.3 tcp传输(客户端)
// tcp客户端
package main
import (
"net"
)
func main() {
conn, _ := net.Dial("tcp", "127.0.0.1:8000")
defer conn.Close()
//发送数据
conn.Write([]byte("are you ok?"))
}
2.7.6锁
1.读时共享,写时独享 写锁优先级比读锁高
2.7.6.1 互斥锁
package main
import (
"fmt"
"sync"
"time"
)
var mutex sync.Mutex
var pipeline = make(chan int)
func printWord(word string) {
mutex.Lock()
for _, value := range word {
fmt.Printf("%c",value)
time.Sleep(time.Microsecond*1000)
}
mutex.Unlock()
}
func main() {
go person1()
go person2()
for {
;
}
}
func person1() {
printWord("1111111111111111111")
pipeline<-666
}
func person2() {
<-pipeline
printWord("222222222222222222")
}
2.7.6.2 互斥锁(管道)
package main
import (
"fmt"
"time"
)
var pipeline = make(chan int)
func printWord(word string) {
for _, value := range word {
fmt.Printf("%c",value)
time.Sleep(time.Microsecond*1000)
}
}
func main() {
go person1()
go person2()
for {
;
}
}
func person1() {
printWord("1111111111111111111")
pipeline<-666
}
func person2() {
<-pipeline
printWord("222222222222222222")
}
2.7.6.3 读写锁
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
var rwMutes sync.RWMutex //锁只有一把 两个属性
var value int //定义全局变量
func main() {
//播种随机数种子
rand.Seed(time.Now().UnixNano())
for i := 0; i < 5; i++ {
go readWord(i + 1)
}
for i := 0; i < 5; i++ {
go writeWord(i + 1)
}
for {
;
}
}
//写
func writeWord(idw int) {
for {
wnum := rand.Intn(1000)
rwMutes.Lock() //以写模式加锁
value = wnum
fmt.Printf("读 %d==> %d\n", idw, wnum)
time.Sleep(time.Microsecond * 300)
rwMutes.Unlock() //
}
}
//读
func readWord(idx int) {
for {
rwMutes.RLock()
rnum := value
fmt.Printf("写 %d==>%d\n", idx, rnum)
rwMutes.RUnlock()
time.Sleep(time.Millisecond * 300)
}
}
2.7.6.4 读写锁管道
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
var rwMutes sync.RWMutex //锁只有一把 两个属性
var value int //定义全局变量
//写
func writeWord(in chan<- int,idw int) {
for {
wnum := rand.Intn(1000)
in<-wnum
fmt.Printf("读 %d==> %d\n", idw, wnum)
time.Sleep(time.Microsecond * 300)
}
}
//读
func readWord(re <-chan int,idx int) {
for {
rnum := <-re
fmt.Printf("写 %d==>%d\n", idx, rnum)
time.Sleep(time.Millisecond * 300)
}
}
func main() {
//播种随机数种子
rand.Seed(time.Now().UnixNano())
ch1 :=make(chan int)
for i := 0; i < 5; i++ {
go readWord(i + 1,ch1)
}
for i := 0; i < 5; i++ {
go writeWord(i + 1,ch1)
}
for {
;
}
}
2.7.6.5条件变量锁
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
var cond sync.Cond //创建全局条件变量
func consumer(in <-chan int, idx int) {
for{
cond.L.Lock()//条件变量对应互斥锁枷锁
for len(in) ==0 { //产品区空 等待生产
cond.Wait() //挂起当前携程,等待全局变量满足
}
num:=<-in
fmt.Printf("%d 消费者消费数据 %d,公共区剩余%d个数据\n",idx,num,len(in))
cond.L.Unlock() //生产结束,解锁互斥锁
cond.Signal() //唤醒阻塞的 消费者
time.Sleep(time.Second)//生产完休息一会,
}
}
func producer(out chan<- int, idx int) {
for{
cond.L.Lock() //条件变量对应互斥锁枷锁
//产品区满 等待消费者消费
for len(out)==3{
cond.Wait() //挂起当前携程,等待全局变量满足
}
num := rand.Intn(1000)
out<-num
fmt.Printf("%d 生产者生产数据 %d,公共区剩余%d个数据\n",idx,num,len(out))
cond.L.Unlock() //生产结束,解锁互斥锁
cond.Signal() //唤醒阻塞的 消费者
time.Sleep(time.Second)//生产完休息一会,给其他协程执行机会
}
}
func main() {
rand.Seed(time.Now().UnixNano())//设置随机数种子
quit := make(chan bool) //创建用于结束通信的channel
product := make(chan int, 3) //产品区(公共区)使用channel模拟
cond.L = new(sync.Mutex)//创建互斥锁和条件变量
for i :=0;i<1 ;i++ {
go producer(product,i+1) //5个生产者
}
for i :=0;i<1 ;i++ {
go consumer(product,i+1) //三个消费者
}
<-quit //主线程阻塞 不结束
}
3.连接mysql
3.1 配置环境变量
3.1.1 设置环境变量 GOPATH
GOPATH
D:\goCode
//项目的安装路径
3.1.2 安装驱动
go get github.com/go-sql-driver/mysql
cmd中打开 这行命令会从github同步代码,同步到GOPATH环境变量下
3.1.3 连接数据库
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
var db *sql.DB
func connectionSql(){
//cannot find package "github.com/go-sql-driver/mysql" in any of:
//idea 配置 file settinf go 配置goPath
var err error
db,err = sql.Open("mysql","root:root@tcp(127.0.0.1:3306)/sxjl?charset=utf8");
//defer db.Close()
if err != nil{
fmt.Printf("connect mysql fail ! [%s]",err)
}
}
3.1.4 查询
/**
查询sql
*/
func querySql(sql string){
rows, err := db.Query(sql)
if err != nil{
fmt.Printf(" mysql fail resion! [%s]",err)
}
//https://blog.csdn.net/kenkao/article/details/47857795?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-6.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-6.nonecase
//字典类型
//构造scanArgs、values两个数组,scanArgs的每个值指向values相应值的地址
columns, _ := rows.Columns()
scanArgs := make([]interface{}, len(columns))
values := make([]interface{}, len(columns))
for i := range values {
scanArgs[i] = &values[i]
}
for rows.Next() {
//将行数据保存到record字典
err = rows.Scan(scanArgs...)
record := make(map[string]string)
for i, col := range values {
if col != nil {
record[columns[i]] = string(col.([]byte))
}
}
fmt.Println(record)
}
}
通用
1.fmt.Sprintf (格式化输出)
%v 按值的本来值输出
%+v 在 %v 的基础上,对结构体字段名和值进行展开
%#v 输出 Go 语言语法格式的值
%T 输出 Go 语言语法格式的类型和值
%% 输出 %% 本体
%b 整型以二进制方式显示
%o 整型以八进制方式显示
%d 整型以十进制方式显示
%x 整型以 十六进制显示
%X 整型以十六进制、字母大写方式显示
%U Unicode 字符
%f 浮点数
%p 指针,十六进制方式显示
2.make 和 new的区别
make 被用来分配引用类型的内存: (make 只能用于 slice,map,channel 三种类型,)
new 被用来分配除了引用类型的所有其他类型的内存: int, string, array等
3.interface{} 类型
interface{} 类型,空接口
//由于没有 implements 关键字,所以所有类型都至少实现了 0 个方法,所以 所有类型都实现了空接口
func PrintAll(vals []interface{}) {
for _, val := range vals {
fmt.Println(val)
}<br>
}
func main() {
names := []string{"stanley", "david", "oscar"}
//**********必须将[]string 转化为 []interface{}
vals := make([]interface{}, len(names))
for i, v := range names {
vals[i] = v
}
PrintAll(vals)
}
4.参数后面的三个点
Go语言函数中有三个点...表示为可变参数,可以接受任意个数的参数。