專科 java轉go 翱翔之路(四)協議通信 鎖,互斥鎖 讀寫鎖 條件變量鎖 連接mysql 查詢

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語言函數中有三個點...表示爲可變參數,可以接受任意個數的參數。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章