欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

golang?中?channel?的詳細(xì)使用、使用注意事項(xiàng)及死鎖問(wèn)題解析

 更新時(shí)間:2022年03月17日 08:34:52   作者:九卷技術(shù)錄  
這篇文章主要介紹了golang?中?channel?的詳細(xì)使用、使用注意事項(xiàng)及死鎖分析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

什么是 channel 管道

它是一個(gè)數(shù)據(jù)管道,可以往里面寫(xiě)數(shù)據(jù),從里面讀數(shù)據(jù)。

channel 是 goroutine 之間數(shù)據(jù)通信橋梁,而且是線程安全的。

channel 遵循先進(jìn)先出原則。

寫(xiě)入,讀出數(shù)據(jù)都會(huì)加鎖。

channel 可以分為 3 種類(lèi)型:

  • 只讀 channel,單向 channel
  • 只寫(xiě) channel,單向 channel
  • 可讀可寫(xiě) channel

channel 還可按是否帶有緩沖區(qū)分為:

帶緩沖區(qū)的 channel,定義了緩沖區(qū)大小,可以存儲(chǔ)多個(gè)數(shù)據(jù)

不帶緩沖區(qū)的 channel,只能存一個(gè)數(shù)據(jù),并且只有當(dāng)該數(shù)據(jù)被取出才能存下一個(gè)數(shù)據(jù)

channel 的基本使用

定義和聲明

// 只讀 channel
var readOnlyChan <-chan int  // channel 的類(lèi)型為 int

// 只寫(xiě) channel
var writeOnlyChan chan<- int
// 可讀可寫(xiě)
var ch chan int
// 或者使用 make 直接初始化
readOnlyChan1 := make(<-chan int, 2)  // 只讀且?guī)Ь彺鎱^(qū)的 channel
readOnlyChan2 := make(<-chan int)   // 只讀且不帶緩存區(qū) channel
writeOnlyChan3 := make(chan<- int, 4) // 只寫(xiě)且?guī)Ь彺鎱^(qū) channel
writeOnlyChan4 := make(chan<- int) // 只寫(xiě)且不帶緩存區(qū) channel
ch := make(chan int, 10)  // 可讀可寫(xiě)且?guī)Ь彺鎱^(qū)
ch <- 20  // 寫(xiě)數(shù)據(jù)
i := <-ch  // 讀數(shù)據(jù)
i, ok := <-ch  // 還可以判斷讀取的數(shù)據(jù)

chan_var.go

package main

import (
    "fmt"
)
func main() {
    // var 聲明一個(gè) channel,它的零值是nil
    var ch chan int
    fmt.Printf("var: the type of ch is %T \n", ch)
    fmt.Printf("var: the val of ch is %v \n", ch)
    if ch == nil {
        // 也可以用make聲明一個(gè)channel,它返回的值是一個(gè)內(nèi)存地址
        ch = make(chan int)
        fmt.Printf("make: the type of ch is %T \n", ch)
        fmt.Printf("make: the val of ch is %v \n", ch)
    }
    ch2 := make(chan string, 10)
    fmt.Printf("make: the type of ch2 is %T \n", ch2)
    fmt.Printf("make: the val of ch2 is %v \n", ch2)
}
// 輸出:
// var: the type of ch is chan int
// var: the val of ch is <nil>
// make: the type of ch is chan int
// make: the val of ch is 0xc000048060
// make: the type of ch2 is chan string
// make: the val of ch2 is 0xc000044060

操作channel的3種方式

操作 channel 一般有如下三種方式:

  • 讀 <-ch
  • 寫(xiě) ch<-
  • 關(guān)閉 close(ch)
操作nil的channel正常channel已關(guān)閉的channel
讀 <-ch阻塞成功或阻塞讀到零值
寫(xiě) ch<-阻塞成功或阻塞panic
關(guān)閉 close(ch)panic成功panic

注意 對(duì)于 nil channel 的情況,有1個(gè)特殊場(chǎng)景:

當(dāng) nil channel 在 select 的某個(gè) case 中時(shí),這個(gè) case 會(huì)阻塞,但不會(huì)造成死鎖。

單向 channel

單向 channel:只讀和只寫(xiě)的 channel

chan_uni.go

package main

import "fmt"
func main() {
	// 單向 channel,只寫(xiě)channel
	ch := make(chan<- int)
	go testData(ch)
	fmt.Println(<-ch)
}
func testData(ch chan<- int) {
	ch <- 10
// 運(yùn)行輸出
// ./chan_uni.go:9:14: invalid operation: <-ch (receive from send-only type chan<- int)
// 報(bào)錯(cuò),它是一個(gè)只寫(xiě) send-only channel

把上面代碼main()函數(shù)里初始化的單向channel,修改為可讀可寫(xiě)channel,再運(yùn)行

chan_uni2.go

package main
import "fmt"
func main() {
    // 把上面代碼main()函數(shù)初始化的單向 channel 修改為可讀可寫(xiě)的 channel
	ch := make(chan int)
	go testData(ch)
	fmt.Println(<-ch)
}
func testData(ch chan<- int) {
	ch <- 10
}
// 運(yùn)行輸出:
// 10
// 沒(méi)有報(bào)錯(cuò),可以正常輸出結(jié)果

帶緩沖和不帶緩沖的 channel

不帶緩沖區(qū) channel

chan_unbuffer.go

package main

import "fmt"
func main() {
    ch := make(chan int) // 無(wú)緩沖的channel
    go unbufferChan(ch)
    for i := 0; i < 10; i++ {
        fmt.Println("receive ", <-ch) // 讀出值
    }
}
func unbufferChan(ch chan int) {
        fmt.Println("send ", i)
        ch <- i // 寫(xiě)入值
// 輸出
send  0
send  1
receive  0
receive  1
send  2
send  3
receive  2
receive  3
send  4
send  5
receive  4
receive  5
send  6
send  7
receive  6
receive  7
send  8
send  9
receive  8
receive  9

帶緩沖區(qū) channel

chan_buffer.go

package main
import (
	"fmt"
)
func main() {
	ch := make(chan string, 3)
	ch <- "tom"
	ch <- "jimmy"
	ch <- "cate"
	fmt.Println(<-ch)
	fmt.Println(<-ch)
	fmt.Println(<-ch)
}
// 運(yùn)行輸出:
// tom
// jimmy
// cate

再看一個(gè)例子:chan_buffer2.go

package main

import (
	"fmt"
	"time"
)
var c = make(chan int, 5)
func main() {
	go worker(1)
	for i := 1; i < 10; i++ {
		c <- i
		fmt.Println(i)
	}
}
func worker(id int) {
	for {
		_ = <-c
// 運(yùn)行輸出:
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9

判斷 channel 是否關(guān)閉

if v, ok := <-ch; ok {
    fmt.Println(ch)
}

說(shuō)明:

  • ok 為 true,讀到數(shù)據(jù),且管道沒(méi)有關(guān)閉
  • ok 為 false,管道已關(guān)閉,沒(méi)有數(shù)據(jù)可讀

讀已經(jīng)關(guān)閉的 channel 會(huì)讀到零值,如果不確定 channel 是否關(guān)閉,可以用這種方法來(lái)檢測(cè)。

range and close

range 可以遍歷數(shù)組,map,字符串,channel等。

一個(gè)發(fā)送者可以關(guān)閉 channel,表明沒(méi)有任何數(shù)據(jù)發(fā)送給這個(gè) channel 了。接收者也可以測(cè)試channel是否關(guān)閉,通過(guò) v, ok := <-ch 表達(dá)式中的 ok 值來(lái)判斷 channel 是否關(guān)閉。上一節(jié)已經(jīng)說(shuō)明 ok 為 false 時(shí),表示 channel 沒(méi)有接收任何數(shù)據(jù),它已經(jīng)關(guān)閉了。

注意:僅僅只能是發(fā)送者關(guān)閉一個(gè) channel,而不能是接收者。給已經(jīng)關(guān)閉的 channel 發(fā)送數(shù)據(jù)會(huì)導(dǎo)致 panic。

Note: channels 不是文件,你通常不需要關(guān)閉他們。那什么時(shí)候需要關(guān)閉?當(dāng)要告訴接收者沒(méi)有值發(fā)送給 channel 了,這時(shí)就需要了。

比如終止 range 循環(huán)。

當(dāng) for range 遍歷 channel 時(shí),如果發(fā)送者沒(méi)有關(guān)閉 channel 或在 range 之后關(guān)閉,都會(huì)導(dǎo)致 deadlock(死鎖)。

下面是一個(gè)會(huì)產(chǎn)生死鎖的例子:

package main

import "fmt"
func main() {
	ch := make(chan int)
	go func() {
		for i := 0; i < 10; i++ {
			ch <- i
		}
	}()
	for val := range ch {
		fmt.Println(val)
	}
	close(ch) // 這里關(guān)閉channel已經(jīng)”通知“不到range了,會(huì)觸發(fā)死鎖。
              // 不管這里是否關(guān)閉channel,都會(huì)報(bào)死鎖,close(ch)的位置就不對(duì)。
              // 且關(guān)閉channel的操作者也錯(cuò)了,只能是發(fā)送者關(guān)閉channel
}
// 運(yùn)行程序輸出
// 0
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
// fatal error: all goroutines are asleep - deadlock!

改正也很簡(jiǎn)單,把 close(ch) 移到 go func(){}() 里,代碼如下

go func() {
    for i := 0; i < 10; i++ {
        ch <- i
    }
    close(ch)
}()

這樣程序就可以正常運(yùn)行,不會(huì)報(bào) deadlock 的錯(cuò)誤了。

把上面程序換一種方式來(lái)寫(xiě),chan_range.go

package main
import (
	"fmt"
)
func main() {
	ch := make(chan int)
	go test(ch)
	for val := range ch { //
		fmt.Println("get val: ", val)
	}
}
func test(ch chan int) {
	for i := 0; i < 5; i++ {
		ch <- i
	}
	close(ch)
}
// 運(yùn)行輸出:
// get val:  0
// get val:  1
// get val:  2
// get val:  3
// get val:  4

發(fā)送者關(guān)閉 channel 時(shí),for range 循環(huán)自動(dòng)退出。

for 讀取channel

用 for 來(lái)不停循環(huán)讀取 channel 里的數(shù)據(jù)。

把上面的 range 程序修改下,chan_for.go

package main
import (
	"fmt"
)
func main() {
	ch := make(chan int)
	go test(ch)
	for {
		val, ok := <-ch
		if ok == false {// ok 為 false,沒(méi)有數(shù)據(jù)可讀
			break // 跳出循環(huán)
		}
		fmt.Println("get val: ", val)
	}
}
func test(ch chan int) {
	for i := 0; i < 5; i++ {
		ch <- i
	}
	close(ch)
}
// 運(yùn)行輸出:
// get val:  0
// get val:  1
// get val:  2
// get val:  3
// get val:  4

select 使用

例子 chan_select.go

package main
import "fmt"
// https://go.dev/tour/concurrency/5
func fibonacci(ch, quit chan int) {
	x, y := 0, 1
	for {
		select {
		case ch <- x:
			x, y = y, x+y
		case <-quit:
			fmt.Println("quit")
			return
		}
	}
}
func main() {
	ch := make(chan int)
	quit := make(chan int)
	go func() {
		for i := 0; i < 10; i++ {
			fmt.Println(<-ch)
		}
		quit <- 0
	}()
	fibonacci(ch, quit)
}
// 運(yùn)行輸出:
// 0
// 1
// 1
// 2
// 3
// 5
// 8
// 13
// 21
// 34
// quit

channel 的一些使用場(chǎng)景

1. 作為goroutine的數(shù)據(jù)傳輸管道

package main

import "fmt"
// https://go.dev/tour/concurrency/2
func sums(s []int, c chan int) {
	sum := 0
	for _, v := range s {
		sum += v
	}
	c <- sum
}
func main() {
	s := []int{7, 2, 8, -9, 4, 0}
	c := make(chan int)
	go sums(s[:len(s)/2], c)
	go sums(s[len(s)/2:], c)
	x, y := <-c, <-c // receive from c
	fmt.Println(x, y, x+y)

用 goroutine 和 channel 分批求和

2. 同步的channel

沒(méi)有緩沖區(qū)的 channel 可以作為同步數(shù)據(jù)的管道,起到同步數(shù)據(jù)的作用。

對(duì)沒(méi)有緩沖區(qū)的 channel 操作時(shí),發(fā)送的 goroutine 和接收的 goroutine 需要同時(shí)準(zhǔn)備好,也就是發(fā)送和接收需要一一配對(duì),才能完成發(fā)送和接收的操作。

如果兩方的 goroutine 沒(méi)有同時(shí)準(zhǔn)備好,channel 會(huì)導(dǎo)致先執(zhí)行發(fā)送或接收的 goroutine 阻塞等待。這就是沒(méi)有緩沖區(qū)的 channel 作為數(shù)據(jù)同步的作用。

gobyexample 中的一個(gè)例子:

package main
import (
	"fmt"
	"time"
)
//https://gobyexample.com/channel-synchronization
func worker(done chan bool) {
	fmt.Println("working...")
	time.Sleep(time.Second)
	fmt.Println("done")
	done <- true
}
func main() {
	done := make(chan bool, 1)
	go worker(done)
	<-done
}

注意:同步的 channel 千萬(wàn)不要在同一個(gè) goroutine 協(xié)程里發(fā)送和接收數(shù)據(jù)。可能導(dǎo)致deadlock死鎖。

3. 異步的channel

有緩沖區(qū)的 channel 可以作為異步的 channel 使用。

有緩沖區(qū)的 channel 也有操作注意事項(xiàng):

如果 channel 中沒(méi)有值了,channel 為空了,那么接收者會(huì)被阻塞。

如果 channel 中的緩沖區(qū)滿了,那么發(fā)送者會(huì)被阻塞。

注意:有緩沖區(qū)的 channel,用完了要 close,不然處理這個(gè)channel 的 goroutine 會(huì)被阻塞,形成死鎖。

package main

import (
	"fmt"
)
func main() {
	ch := make(chan int, 4)
	quitChan := make(chan bool)
	go func() {
		for v := range ch {
			fmt.Println(v)
		}
		quitChan <- true // 通知用的channel,表示這里的程序已經(jīng)執(zhí)行完了
	}()
	ch <- 1
	ch <- 2
	ch <- 3
	ch <- 4
	ch <- 5
	close(ch)  // 用完關(guān)閉channel
	<-quitChan // 接到channel通知后解除阻塞,這也是channel的一種用法
}

4.channel 超時(shí)處理

channel 結(jié)合 time 實(shí)現(xiàn)超時(shí)處理。

當(dāng)一個(gè) channel 讀取數(shù)據(jù)超過(guò)一定時(shí)間還沒(méi)有數(shù)據(jù)到來(lái)時(shí),可以得到超時(shí)通知,防止一直阻塞當(dāng)前 goroutine。

chan_timeout.go

package main
import (
	"fmt"
	"time"
)
func main() {
	ch := make(chan int)
	quitChan := make(chan bool)
	go func() {
		for {
			select {
			case v := <-ch:
				fmt.Println(v)
			case <-time.After(time.Second * time.Duration(3)):
				quitChan <- true
				fmt.Println("timeout, send notice")
				return
			}
		}
	}()
	for i := 0; i < 4; i++ {
		ch <- i
	}
	<-quitChan // 輸出值,相當(dāng)于收到通知,解除主程阻塞
	fmt.Println("main quit out")
}

使用 channel 的注意事項(xiàng)及死鎖分析

未初始化的 channel 讀寫(xiě)關(guān)閉操作

1.讀:未初始化的channel,讀取里面的數(shù)據(jù)時(shí),會(huì)造成死鎖deadlock

var ch chan int
<-ch  // 未初始化channel讀數(shù)據(jù)會(huì)死鎖

2.寫(xiě):未初始化的channel,往里面寫(xiě)數(shù)據(jù)時(shí),會(huì)造成死鎖deadlock

var ch chan int
ch<-  // 未初始化channel寫(xiě)數(shù)據(jù)會(huì)死鎖

3.關(guān)閉:未初始化的channel,關(guān)閉該channel時(shí),會(huì)panic

var ch chan int
close(ch) // 關(guān)閉未初始化channel,觸發(fā)panic

已初始化的 channel 讀寫(xiě)關(guān)閉操作

1. 已初始化,沒(méi)有緩沖區(qū)的channel

 // 代碼片段1
   func main() {
        ch := make(chan int)
        ch <- 4
   }

代碼片段1:沒(méi)有緩沖channel,且只有寫(xiě)入沒(méi)有讀取,會(huì)產(chǎn)生死鎖

// 代碼片段2
   func main() {
       ch := make(chan int)
       val, ok := <-ch
   }

代碼片段2:沒(méi)有緩沖channel,且只有讀取沒(méi)有寫(xiě)入,會(huì)產(chǎn)生死鎖

// 代碼片段3
   func main() {
       ch := make(chan int)
       val, ok := <-ch
       if ok {
           fmt.Println(val)
       }
       ch <- 10 // 這里進(jìn)行寫(xiě)入。但是前面已經(jīng)產(chǎn)生死鎖了
   }

代碼片段3:沒(méi)有緩沖channel,既有寫(xiě)入也有讀出,但是在代碼 val, ok := <-c 處已經(jīng)產(chǎn)生死鎖了。下面代碼執(zhí)行不到。

// 代碼片段4
   func main() {
   	ch := make(chan int)
   	ch <- 10
   	go readChan(ch)
   	
       time.Sleep(time.Second * 2)
   }
   
   func readChan(ch chan int) {
   	for {
   		val, ok := <-ch
   		fmt.Println("read ch: ", val)
   		if !ok {
   			break
   		}
   	}
   }

代碼片段4:沒(méi)有緩沖channel,既有寫(xiě)入也有讀出,但是運(yùn)行程序后,報(bào)錯(cuò) fatal error: all goroutines are asleep - deadlock! 。

這是因?yàn)橥?channle 里寫(xiě)入數(shù)據(jù)的代碼 ch <- 10,這里寫(xiě)入數(shù)據(jù)時(shí)就已經(jīng)產(chǎn)生死鎖了。把 ch<-10go readChan(ch) 調(diào)換位置,程序就能正常運(yùn)行,不會(huì)產(chǎn)生死鎖。

 // 代碼片段5
   func main() {
   	ch := make(chan int)
   
   	go writeChan(ch)
   	for {
   		val, ok := <-ch
   		fmt.Println("read ch: ", val)
   		if !ok {
   			break
   		}
   	}
   	time.Sleep(time.Second)
       fmt.Println("end")
   }
   func writeChan(ch chan int) {
   	for i := 0; i < 4; i++ {
   		ch <- i

代碼片段5:沒(méi)有緩沖的channel,既有寫(xiě)入,也有讀出,與上面幾個(gè)代碼片段不同的是,寫(xiě)入channel的數(shù)據(jù)不是一個(gè)。

思考一下,這個(gè)程序會(huì)產(chǎn)生死鎖嗎?10 秒時(shí)間思考下,先不要看下面。

也會(huì)產(chǎn)生死鎖,它會(huì)輸出完數(shù)據(jù)后,報(bào)錯(cuò) fatal error: all goroutines are asleep - deadlock!。

為什么呢?這個(gè)程序片段,既有讀也有寫(xiě)而且先開(kāi)一個(gè)goroutine寫(xiě)數(shù)據(jù),為什么會(huì)死鎖?

原因在于 main() 里的 for 循環(huán)。可能你會(huì)問(wèn),不是有 break 跳出 for 循環(huán)嗎?代碼是寫(xiě)了,但是程序并沒(méi)有執(zhí)行到這里。

因?yàn)?for 會(huì)不停的循環(huán),而 val, ok := <-ch, 這里 ok 值一直是 true,因?yàn)槌绦蚶锊](méi)有哪里關(guān)閉 channel 啊。你們可以打印這個(gè) ok 值看一看是不是一直是 true。當(dāng) for 循環(huán)把 channel 里的值讀取完了后,程序再次運(yùn)行到 val, ok := <-ch 時(shí),產(chǎn)生死鎖,因?yàn)?channel 里沒(méi)有數(shù)據(jù)了。

找到原因了,那解決辦法也很簡(jiǎn)單,在 writeChan 函數(shù)里關(guān)閉 channel,加上代碼 close(ch)。告訴 for 我寫(xiě)完了,關(guān)閉 channel 了。

加上關(guān)閉 channel 代碼后運(yùn)行程序:

read ch:  0 , ok:  true
read ch:  1 , ok:  true
read ch:  2 , ok:  true
read ch:  3 , ok:  true
read ch:  0 , ok:  false
end

程序正常輸出結(jié)果。

對(duì)于沒(méi)有緩沖區(qū)的 channel (unbuffered channel) 容易產(chǎn)生死鎖的幾個(gè)代碼片段分析,總結(jié)下:

  • channel 要用 make 進(jìn)行初始化操作
  • 讀取和寫(xiě)入要配對(duì)出現(xiàn),并且不能在同一個(gè) goroutine 里
  • 一定先用 go 起一個(gè)協(xié)程執(zhí)行讀取或?qū)懭氩僮?/li>
  • 多次寫(xiě)入數(shù)據(jù),for 讀取數(shù)據(jù)時(shí),寫(xiě)入者注意關(guān)閉 channel(代碼片段5)

2. 已初始化,有緩沖區(qū)的 channel

// 代碼片段1
func main() {
    ch := make(chan int, 1)
    val, ok := <-ch
}

代碼片段1:有緩沖channel,先讀數(shù)據(jù),這里會(huì)一直阻塞,產(chǎn)生死鎖。

// 代碼片段2
   func main() {
       ch := make(chan int, 1)
       ch <- 10
   }

代碼片段2:同代碼片段1,有緩沖channel,只有寫(xiě)沒(méi)有讀,也會(huì)阻塞,產(chǎn)生死鎖。

 // 代碼片段3
   func main() {
   	ch := make(chan int, 1)
   	ch <- 10
   
   	val, ok := <-ch
   	if ok {
   		fmt.Println(val, ok)
   	}
   }

代碼片段3:有緩沖的channel,有讀有寫(xiě),正常的輸出結(jié)果。

有緩沖區(qū)的channel總結(jié):

  • 如果 channel 滿了,發(fā)送者會(huì)阻塞
  • 如果 channle 空了,接收者會(huì)阻塞
  • 如果在同一個(gè) goroutine 里,寫(xiě)數(shù)據(jù)操作一定在讀數(shù)據(jù)操作前

參考

https://go.dev/tour/concurrency
https://go.dev/ref/spec#Channel_types
https://go.dev/ref/spec#Send_statements
https://go.dev/ref/spec#Receive_operator
https://go.dev/ref/spec#Close
https://go.dev/doc/effective_go#channels
https://go.dev/ref/spec#Select_statements
https://gobyexample.com/
Concurrency is not parallelism - The Go Programming Language

到此這篇關(guān)于golang 中 channel 的詳細(xì)使用、使用注意事項(xiàng)及死鎖分析的文章就介紹到這了,更多相關(guān)golang 中 channel 使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語(yǔ)言讀寫(xiě)鎖RWMutex的源碼分析

    Go語(yǔ)言讀寫(xiě)鎖RWMutex的源碼分析

    本篇文章我們將一起來(lái)學(xué)習(xí)下Go語(yǔ)言中的讀寫(xiě)鎖sync.RWMutex。文中的示例講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-10-10
  • Golang中數(shù)據(jù)結(jié)構(gòu)Queue的實(shí)現(xiàn)方法詳解

    Golang中數(shù)據(jù)結(jié)構(gòu)Queue的實(shí)現(xiàn)方法詳解

    這篇文章主要給大家介紹了關(guān)于Golang中數(shù)據(jù)結(jié)構(gòu)Queue的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-09-09
  • 一文詳解Golang中new和make的區(qū)別

    一文詳解Golang中new和make的區(qū)別

    在Go語(yǔ)言中,new和make是兩個(gè)用于創(chuàng)建對(duì)象的內(nèi)建函數(shù)。本文將詳細(xì)介紹new和make的區(qū)別,并通過(guò)多個(gè)方面的分析和代碼示例,幫助大家理解它們的使用場(chǎng)景
    2023-05-05
  • Go語(yǔ)言中日志統(tǒng)一處理詳解

    Go語(yǔ)言中日志統(tǒng)一處理詳解

    在現(xiàn)代軟件開(kāi)發(fā)中,日志記錄是一項(xiàng)至關(guān)重要的任務(wù),它不僅幫助開(kāi)發(fā)人員診斷問(wèn)題,還有助于監(jiān)控和維護(hù)應(yīng)用程序,本文主要來(lái)和大家聊聊日志的統(tǒng)一處理,感興趣的小伙伴可以了解下
    2024-01-01
  • Go單元測(cè)試工具gomonkey的使用

    Go單元測(cè)試工具gomonkey的使用

    本文主要介紹了Go單元測(cè)試工具gomonkey的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • go內(nèi)存隊(duì)列l(wèi)ist VS slice實(shí)現(xiàn)方式對(duì)比分析

    go內(nèi)存隊(duì)列l(wèi)ist VS slice實(shí)現(xiàn)方式對(duì)比分析

    這篇文章主要為大家介紹了go內(nèi)存隊(duì)列l(wèi)ist VS slice實(shí)現(xiàn)方式對(duì)比分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • golang 函數(shù)以及函數(shù)和方法的詳解及區(qū)別

    golang 函數(shù)以及函數(shù)和方法的詳解及區(qū)別

    這篇文章主要介紹了golang 函數(shù)以及函數(shù)和方法的區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • Go?net?http超時(shí)應(yīng)用場(chǎng)景全面詳解

    Go?net?http超時(shí)應(yīng)用場(chǎng)景全面詳解

    HTTP是一個(gè)復(fù)雜的多階段協(xié)議,因此沒(méi)有一個(gè)一刀切的超時(shí)解決方案,在這篇文章中,我將分解您可能需要應(yīng)用超時(shí)的各個(gè)階段,并研究在服務(wù)器端和客戶(hù)端上執(zhí)行超時(shí)的不同方法
    2024-01-01
  • 對(duì)Go語(yǔ)言中的context包源碼分析

    對(duì)Go語(yǔ)言中的context包源碼分析

    這篇文章主要對(duì)Go語(yǔ)言中的context包源碼進(jìn)行分析,context包析是1.15,context包定義了一個(gè)Context類(lèi)型過(guò)這個(gè)Context接口類(lèi)型,?就可以跨api邊界/跨進(jìn)程傳遞一些值,下面我們就來(lái)對(duì)context包源碼進(jìn)行分析,需要的小伙伴可以參考一下
    2022-02-02
  • Go?語(yǔ)言進(jìn)階freecache源碼學(xué)習(xí)教程

    Go?語(yǔ)言進(jìn)階freecache源碼學(xué)習(xí)教程

    這篇文章主要為大家介紹了Go?語(yǔ)言進(jìn)階freecache源碼學(xué)習(xí)教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04

最新評(píng)論