Golang基礎速度二十二(終結篇)

huxiaobai_001發表於2020-07-29

簡單基礎總結

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    /*
    //字串的一些操作
    //1.獲取字串的長度
    var str = "this is str"
    fmt.Println(len(str))
    //2.拼接字串
    var str1 = "您好"
    var str2 = "huxiaobai"
    fmt.Println(str1+str2)
    //3.分割字串
    var str3 = "123-456-789"
    split := strings.Split(str3, "-")
    fmt.Println(split[0])
    //4.判斷字串是否包含另一個字串
    var str4 = "this is golang"
    contains := strings.Contains(str4, "golang")
    fmt.Println(contains)
    //5.判斷字串出現的位置
    var str5 = "this is golang"
    index := strings.Index(str5, "this")  //從前往後  如果返回-1表示沒有
    fmt.Println(index)
    index1 := strings.LastIndex(str5,"go")  //從後往前 如果返回-1表示沒有
    fmt.Println(index1)
    //6.拼接字串  把切片裡面的元素用*連結起來
    var str6 = "123-456-789"
    var arr = strings.Split(str6,"-")
    var str7 = strings.Join(arr,"*")
    fmt.Println(str7)
    //7.修改字串
    var b1 = "big"
    bytes := []byte(b1)
    bytes[0]='a'
    fmt.Println(string(bytes))

     */

    /*
    //注意:轉換的時候建議從低位轉換成高位 高位轉換為低位的時候如果不成功就會溢位和我們想要的結果會不一樣
    //整形和整形之間的轉換
        //整形和整形之間的轉換   int64位置轉換為int32位
        var a int64  = 16
        i := int32(a)
        fmt.Println(reflect.TypeOf(i))  //通過反射獲取到最終的資料型別
        //不同型別的整形相加 需低型別轉為高型別 建議哈! 低往高了轉!
        var b int8 = 32
        var c int16 = 30
        fmt.Println(int16(b)+c)

    //整形和浮點型之間的轉換
        //整形和浮點型運算 建議將整形轉為浮點型然後再和浮點型進行運算
        var e float32 = 20.23
        var f int = 40
        fmt.Println(e+float32(f))

     */

    /*
    //通過Sprintf()將不同型別轉換為string型別
    //sprintf的作用是將一個格式化的字串輸出到一個目的字串中,而printf是將一個格式化的字串輸出到螢幕
    //不同型別轉換為string型別%後邊跟著不同的符號
    //int為%d   float為%f    bool為%t     byte為%c
        var g int = 20
        var h float64 = 12.343
        var i bool = true
        var k byte  = 'a'
        //通過Sprintf()進行型別轉換
        str1 := fmt.Sprintf("%d",g) // %d表示轉為十進位制 用在對int型別轉為string
        fmt.Printf("值:%v 型別:%T\n",str1,str1)
        fmt.Println("-------------------------------------------")

        str2 := fmt.Sprintf("%.2f",h) // %f 表示將float型別轉為string型別  %.2f表示保留兩位小數
        fmt.Printf("值:%v 型別:%T\n",str2,str2)
        fmt.Println("-------------------------------------------")

        str3 := fmt.Sprintf("%t",i)
        fmt.Printf("值:%v 型別:%T\n",str3,str3)  // %t 表示將布林型別轉換為string型別 最終要麼true 要麼false
        fmt.Println("-------------------------------------------")

        str4 := fmt.Sprintf("%c",k)  // %c 表示將字元原樣輸出
        fmt.Printf("值:%v 型別:%T\n",str4,str4)
        fmt.Println("-------------------------------------------")
     */


    /*
    //通過strconv()包進行型別轉換
    //1.通過strconv包 把其他型別轉換成string型別
    var l int = 20
    //strconv.FormatInt()  將int型別轉為string型別 第一個引數必須是int64() 第二個引數傳入int型別的進位制一般都是10進位制
    str1 := strconv.FormatInt(int64(l), 10)
    fmt.Printf("值:%v 型別:%T\n",str1,str1)

    var m float32 = 12.335
    //strconv.FormatFloat()  將float型別轉為string型別 第一個引數必須是float64() 第二個引數傳入要格式化的型別一般傳f即可是一個字元 第三個引數保留的小數點但-1表示不對小數點格式化  第四個參數列示格式化的型別要麼32要麼64都行
    str2 := strconv.FormatFloat(float64(m),'f',-1,32)
    fmt.Printf("值:%v 型別:%T\n",str2,str2)

    //strconv.FormatBool()  將bool型別轉換為string型別  意義不大
    str3 := strconv.FormatBool(true)
    fmt.Printf("值:%v 型別:%T\n",str3,str3)

    var n byte  = 'a'
    //strconv.FormatUnit()  將字元型別轉為字串  轉為之後會是一個asc碼跟他媽數字似的 沒啥意思!
    str4:=strconv.FormatUint(uint64(n),10)
    fmt.Printf("值:%v 型別:%T\n",str4,str4)

    //2.將string型別轉為數值型別
    str5 := "123456"
    //先看看之前的型別和值
    fmt.Printf("值:%v 型別:%T\n",str5,str5)
    //strconv.ParseInt() 將字串型別轉為數值型別  第一個引數string資料 第二個引數轉為10進位制  第三個引數位數16 32 64
    num,_ := strconv.ParseInt(str5,10,64)
    fmt.Printf("值:%v 型別:%T\n",num,num)

    str6 := "1234.56"
    //strconv.ParseFloat()第一個引數傳string資料  第二個引數傳位數32 64
    num1, _ := strconv.ParseFloat(str6, 32)
    fmt.Printf("值:%v 型別:%T\n",num1,num1)


    //3.string型別也能轉為bool型但是我們不建議這麼做 因為沒有意義
    //4.bool型和int數值型別不能相互轉換

     */

    /*
    //時間
    //1.格式化輸出年月日時分秒
    timeObj := time.Now()
    //列印出來的時間並不是我們想要的格式
    fmt.Println(timeObj)
    //調取時間物件裡面的方法獲取年月日時分秒
    year := timeObj.Year()
    month := timeObj.Month()
    day := timeObj.Day()
    hour := timeObj.Hour()
    minute := timeObj.Minute()
    second := timeObj.Second()
    //格式化列印輸出
    fmt.Printf("%d-%d-%d %d:%d:%d\n",year,month,day,hour,minute,second)
    //注意: %02d 中的2表示寬度 如果整數不夠2列就補上0
    fmt.Printf("%d-%02d-%02d %02d:%02d:%02d\n",year,month,day,hour,minute,second)

    //2.格式化輸出年月日時分秒
    // 2006表示年 01表示月 02表示日 03表示時(12小時制)如果03改成15則是24小時制     04表示分 05表示秒  固定寫法就要是2006-01-02 03:04:05  你改一個數字就會發生時間上的錯誤 當然-你可以替換成別的/或者其他
    //2006-01-02 03:04:05  這是golang裡面格式化的模板模板模板哈
    timeObj1 := time.Now()
    var str6 = timeObj1.Format("2006-01-02 03:04:05") //2020-07-22 04:40:37 獲取到的時間你不知道是上午還是下午
    fmt.Println(str6)
    //如果03改成15則是24小時制
    var str7 = timeObj1.Format("2006-01-02 15:04:05") //2020-07-22 16:40:37 獲取到的時間你不知道是上午還是下午
    fmt.Println(str7)

    //3.獲取當前時間的時間戳
    timeObj2 := time.Now()
    unixTime := timeObj2.Unix()
    fmt.Println(unixTime)

    //4.將時間戳轉換成日期格式
    unixTime1 := 1595407628
    //time.Unix()傳入時間戳會返回時間物件 第一個引數必須是int64位 第二個引數是微秒數沒有則傳入0 返回的是Time時間型別
    timeObj3 := time.Unix(int64(unixTime1),0)
    str8 := timeObj3.Format("2006-01-01 03:04:05")
    fmt.Println(str8)

    //5.日期字串轉換成時間戳
    var str9 = "2020-07-07 04:47:08"
    var temp = "2006-01-02 03:04:05"  //相當於模板樣例  啥格式的   這個要和上邊的str9的格式保持一致才行
    //將日期字串轉為時間戳  time.ParseInLocation() 第一個引數模板樣例 第二個引數日期字串 第三個引數time,Local  返回的是Time型別
    timeObj4, _ := time.ParseInLocation(temp, str9, time.Local)
    fmt.Println(timeObj4)  //列印一下日期
    fmt.Println(timeObj4.Unix())  //日期調取Unix()便獲取到了時間戳

    //6.time包裡面的常量
    fmt.Println(time.Microsecond)  //獲取1微秒
    fmt.Println(time.Millisecond)  //獲取1ms
    fmt.Println(time.Second) //獲取1s
    fmt.Println(time.Minute) //獲取1分鐘
    fmt.Println(time.Hour) //獲取一小時

    //7.時間操作函式
    //add() 當前時間的基礎上增加1小時或者1分鐘或者1s......
    timeObj5 := time.Now()
    fmt.Println(timeObj5)
    fmt.Println(timeObj5.Add(time.Hour))
    //計算兩個時間相差多少個小時
    var starTime = "2020-08-01 00:00:00"
    var endTime = "2020-08-02 00:00:00"
    t1, err := time.ParseInLocation("2006-01-02 15:04:05", starTime, time.Local)
    t2, err := time.ParseInLocation("2006-01-02 15:04:05", endTime, time.Local)
    if err == nil && t1.Before(t2) {
        diff := t2.Unix() - t1.Unix()
        hour := diff/3600
        fmt.Println(hour)
    }else{
        fmt.Println("報錯")
    }
    //利用sub計算兩個時間的差值
    var st1 = "2020-07-22 00:00:00"
    var st2 = "2020-07-23 00:00:00"
    st11,err := time.ParseInLocation("2006-01-02 15:04:05",st1,time.Local)
    st22,err := time.ParseInLocation("2006-01-02 15:04:05",st2,time.Local)
    if err ==  nil && st11.Before(st22) {
        var ret = st22.Sub(st11)
        fmt.Println(ret)
    }else{
        fmt.Println("error")
    }
    //before和after的使用
    var stime1 = "2020-07-22 00:00:00"
    var stime2 = "2020-07-23 00:00:00"
    stime11,err := time.ParseInLocation("2006-01-02 15:04:05",stime1,time.Local)
    stime22,err := time.ParseInLocation("2006-01-02 15:04:05",stime2,time.Local)
    //stime11是否是在stime22的前邊
    if stime11.Before(stime22) {
        fmt.Println("yes")
    }else{
        fmt.Println("no")
    }

    //8.定時器
    ticker := time.NewTicker(time.Second) //定義一個1s間隔的定時器
    n :=0
    //死迴圈裡面遍歷ticker裡面的C 返回的是時間Time格式  比如你上邊是間隔1s 那麼這裡就是返回的每隔1s的時間Time格式
    for i := range ticker.C {
        fmt.Println(i) //每秒都會執行的任務
        n++
        if n > 5 {
            //滿足條件 則需要將ticker在記憶體當中銷燬掉
            ticker.Stop()
            break
        }
    }
    fmt.Println("程式執行完畢!")

    //9.第二種定時器的實現
    y := 0
    for {
        time.Sleep(time.Second)  //睡眠1s
        if y > 5 {
            break
        }else{
            fmt.Println("執行中")
        }
        y++
    }
    fmt.Println("for程式執行完畢!")

     */

    /*
    //float型別計算影響精度的問題  為了避免精度損失我們使用decimal包
    //加法
    var num1 float64 = 3.1
    var num2 float64 = 4.2
    d1 := decimal.NewFromFloat(num1).Add(decimal.NewFromFloat(num2))
    fmt.Println(d1)

    //減法
    m1 := 8.9
    m2 := 4.2
    d2 := decimal.NewFromFloat(m1).Sub(decimal.NewFromFloat(m2))
    fmt.Println(d2)

    //乘法
     f1 := 1.2
     f2 := 3.9
     f3 := decimal.NewFromFloat(f1).Mul(decimal.NewFromFloat(f2))
     fmt.Println(f3)

     */


    /*
    //陣列切片排序 sort包的使用
    //正序排序
    intList := []int{2, 4, 3, 5, 7, 6, 9, 8, 1, 0}
    float8List := []float64{4.2, 5.9, 12.4, 10.2, 50.7, 99.9, 31.4, 27.81828, 3.14}
    stringList := []string{"a", "c", "b", "z", "x", "w", "y", "d", "f", "i"}
    //對切片或者陣列裡面的整型進行正序排序 從小到大
    sort.Ints(intList)
    //對切片或者陣列裡面的浮點型進行正序排序 從小到大
    sort.Float64s(float8List)
    //對切片或者陣列裡面的字串型別進行正序排序 從小到大
    sort.Strings(stringList)
    //列印一下看看
    fmt.Println(intList)
    fmt.Println(float8List)
    fmt.Println(stringList)

    //倒敘排序
    intList1 := []int{2, 4, 3, 5, 7, 6, 9, 8, 1, 0}
    float8List1 := []float64{4.2, 5.9, 12.4, 10.2, 50.7, 99.9, 31.4, 27.81828, 3.14}
    stringList1 := []string{"a", "c", "b", "z", "x", "w", "y", "d", "f", "i"}
    //對切片或者陣列裡面的整型進行正序排序 從大到小
    sort.Sort(sort.Reverse(sort.IntSlice(intList1)))
    //對切片或者陣列裡面的浮點型進行正序排序 從大到小
    sort.Sort(sort.Reverse(sort.Float64Slice(float8List1)))
    //對切片或者陣列裡面的字串型別進行正序排序 從大到小
    sort.Sort(sort.Reverse(sort.StringSlice(stringList1)))
    //列印一下
    fmt.Println(intList1)
    fmt.Println(float8List1)
    fmt.Println(stringList1)

     */

    //golang當中的併發安全和鎖機制
    //互斥鎖案例
    //for r := 0; r<20; r++{
    //    wg.Add(1)
    //    go test111()
    //}
    //wg.Wait()

    //讀寫鎖案例
    //開啟10個協程執行讀操作
    for i:=0;i<10;i++{
        wg.Add(1)
        go write()
    }
    //開啟10個協程執行寫操作
    for i:=0;i<10;i++{
        wg.Add(1)
        go read()
    }
    wg.Wait()

}

// 以下是為了配合互斥鎖的相關程式碼
var count int
var wg sync.WaitGroup
var mutex sync.Mutex
//讀寫鎖需要使用 sync.REMutex
var mutex1 sync.RWMutex

func test111(){
    //因為起來了20個協程 這20個協程之間一定會存在競爭關係 都會去改變count的值 所以容易造成錯誤的發生 加上了互斥鎖之後 一個協程鎖定了那麼其他協程無法操作 只有等到當前協程解鎖之後才能繼續操作!
    //加鎖
    mutex.Lock()
    count++
    fmt.Println("the count is :",count)
    time.Sleep(time.Millisecond)
    //解鎖
    mutex.Unlock()

    wg.Done()
}

//以下是為了配合讀寫鎖的相關程式碼
//寫的方法
func write(){
    //寫鎖   寫的時候其他協程啥也幹不了哈!
    mutex1.Lock()
    fmt.Println("執行寫操作")
    time.Sleep(time.Second * 2)
    mutex1.Unlock()
    wg.Done()
}
//讀的方法
func read(){
    //我們在這裡加的是讀鎖  協程可以併發的讀取  但是寫的協程在執行的時候他是無法執行的  因為當前協程的寫會阻塞其他協程的讀和其他協程的寫
    mutex1.RLock()
    fmt.Println("執行讀操作")
    time.Sleep(time.Second * 2)
    mutex1.RUnlock()
    wg.Done()
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結

胡軍

相關文章