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語言函數中有三個點...表示爲可變參數,可以接受任意個數的參數。