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

golang切片拷貝的實(shí)現(xiàn)

 更新時(shí)間:2024年10月15日 10:22:37   作者:快刀一哥  
在Golang中,切片的淺拷貝只復(fù)制指向?qū)ο蟮闹羔?而深拷貝則復(fù)制數(shù)據(jù)本身,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

golang切片有淺拷貝和深拷貝的區(qū)別

1、深拷貝(Deep Copy)

拷貝的是數(shù)據(jù)本身,創(chuàng)造一個(gè)樣的新對象,新創(chuàng)建的對象與原對象不共享內(nèi)存,新創(chuàng)建的對象在內(nèi)存中開辟一個(gè)新的內(nèi)存地址,新對象值修改時(shí)不會(huì)影響原對象值。既然內(nèi)存地址不同,釋放內(nèi)存地址時(shí),可分別釋放。

值類型的數(shù)據(jù),默認(rèn)全部都是深復(fù)制,Array、Int、String、Struct、Float,Bool。

2、淺拷貝(Shallow Copy)

拷貝的是數(shù)據(jù)地址,只復(fù)制指向的對象的指針,此時(shí)新對象和老對象指向的內(nèi)存地址是一樣的,新對象值修改時(shí)老對象也會(huì)變化。釋放內(nèi)存地址時(shí),同時(shí)釋放內(nèi)存地址。

引用類型的數(shù)據(jù),默認(rèn)全部都是淺復(fù)制,Slice,Map。

去若是淺拷貝,原始的切片變化后所有的切片都會(huì)變化,無論切片是否在一個(gè)函數(shù),還是一個(gè)goroutine中,都會(huì)發(fā)生變化

如下代碼為例子

package main

import "fmt"

func main() {
	
	// 創(chuàng)建一個(gè)切片
	originalSlice := []int{1, 2, 3, 4, 5}

	// 使用切片[:]操作符創(chuàng)建淺拷貝
	shallowCopy := originalSlice[:]
	shallowCopy2 := make([]int, len(shallowCopy))
	copy(shallowCopy2, originalSlice)

	// 修改原始切片的元素
	originalSlice[0] = 100

	// 輸出原始切片和淺拷貝的切片
	fmt.Println("Original Slice:", originalSlice)
	fmt.Println("Shallow Copy:", shallowCopy)
	fmt.Println("Shallow Copy2:", shallowCopy2)
}

如下代碼問題困擾了好久,才發(fā)現(xiàn)是切片賦值的問題

func (sf *ServerSession) running(ctx context.Context, subcom []uint8) {
	var err error
	var bytesRead int

	defer func() {
		sf.conn.Close()

	}()
	go sf.prehandler()

	raw := make([]byte, tcpAduMaxSize)

	for {
		select {
		case <-ctx.Done():
			err = errors.New("server active close")
			xlog.Errorln(err)
			return
		default:
		}

		err = sf.conn.SetReadDeadline(time.Now().Add(sf.readTimeout))
		if err != nil {
			xlog.Errorln("set read tcp data time deadline error:", err)
		}
		count, err := sf.conn.Read(raw)

		if err != nil {
			if err != io.EOF && err != io.ErrClosedPipe || strings.Contains(err.Error(), "use of closed network connection") {
				return
			}

			if e, ok := err.(net.Error); ok && !e.Temporary() {
				return
			}

			if bytesRead == 0 && err == io.EOF {
				err = fmt.Errorf("remote client closed, %v", err)
				xlog.Errorln(err)
				return
			}
			// cnt >0 do nothing
			// cnt == 0 && err != io.EOF continue do it next
		}
		adu := raw[:count]

		prodata := new(ProcessData)
		prodata.adu = make([]byte, len(adu))
		copy(prodata.adu, adu)
		prodata.count = count
		prodata.subcom = subcom
		Prodatach <- prodata

	}
}

func (sf *ServerSession) prehandler() {
	for {
		select {
		case prodata := <-Prodatach:
			go sf.prerunhandler(prodata)

		}
	}
}
func (sf *ServerSession) prerunhandler(prodata *ProcessData) {
	length := prodata.count
	adu := make([]byte, len(prodata.adu))
	copy(adu, prodata.adu)
	subcom := prodata.subcom
	xlog.Debug("run handler input1 out1 adu [% X] length is:%d\n", adu, length)
	//可能一次讀出來多個(gè)數(shù)據(jù)包 增加處理方式 @20240704
	//直接在for循環(huán)中使用
	for length > 0 {
		headdata := adu[:gaHeaderSize]
		head1 := new(gadataHeader)
		buf1 := bytes.NewReader(headdata)
		err := binary.Read(buf1, binary.BigEndian, head1)
		if err != nil {
			xlog.Errorln("ga server decode errr:", err)
		}
		xlog.Debugln("pre process packect SN:", head1.SN)
		galength := int(head1.Datalength) + gaHeaderSize

		if galength <= len(adu) {
			adu1 := adu[:galength]
			xlog.Debug("run handler input out adu [% X ],galength is:%d subcom is %d length is:%d\n", adu1, galength, subcom, length)
			sf.runhandler(adu1, galength, subcom)
			adu = adu[galength:]
			length -= galength

		} else {
			xlog.Debug("data length is %d, adu length is:%d\n", head1.Datalength, len(adu))
			break
		}

	}
}
func (sf *ServerSession) runhandler(adu []byte, count int, subcom []uint8) {
	if count < gaHeaderSize {
		return
	}
	xlog.Debug("run handler input adu [% X ],count is:%d subcom is %d", adu, count, subcom)
	// xlog.Debug("recive data [% x] count is % d \n", adu, count)
	head1 := new(gadataHeader)
	data := adu[:gaHeaderSize]
	buf1 := bytes.NewReader(data)
	err := binary.Read(buf1, binary.BigEndian, head1)
	if err != nil {
		xlog.Errorln("ga server decode errr:", err)
	}
	xlog.Debugln("gaserver head sn:", head1.SN)

	if !Find(subcom, head1.Subcomid) {
		xlog.Debug("subcom: %d is not in array %d \n", head1.Subcomid, subcom)
		return
	}
	// check head ProtocolIdentifier
	// if binary.BigEndian.Uint16(adu[2:]) != tcpProtocolIdentifier {
	// 	rdCnt, length = 0, tcpHeaderMbapSize
	// 	continue
	// }
	length := int(head1.Datalength) + gaHeaderSize
	if count == length {
		xlog.Debug("start decode packet SN is:%d subcom is %d data length is:%d\n", head1.SN, head1.Subcomid, head1.Datalength)
		if err = sf.frameHandler(adu); err != nil {
			xlog.Errorln("gaserver decode error:", err)
			return
		}
	} else {
		xlog.Debug("head data length: %d is not right %d \n", head1.Datalength, count)
		///此處經(jīng)常出現(xiàn)問題
		xlog.Debug("adu data is [% X] \n", adu)
	}
}
func Find(subcoms []uint8, subcom uint8) bool {
	for i := 0; i < len(subcoms); i++ {
		if subcoms[i] == subcom {
			return true
		}
	}
	return false
}

出現(xiàn)非常奇怪的問題切片內(nèi)容經(jīng)常莫名奇妙的改變,最后發(fā)現(xiàn)是切片賦值的問題

1449[xx] 2024-07-05 16:28:03.428417 run handler input1 out1 adu [00 C4 11 0A 01 A3 00 0A 00 A1 42 79 08 20 1F 75 A0 00
 00 C5 11 06 01 A3 00 18 00 79 00 00 00 00 00 C0 C2 92 00 00 00 8D 42 95 85 C5 00 97 42 92 3D 71 ] length is:50
1450 [xx] 2024-07-05 16:28:03.428496 pre process packect SN: 196

1452[xx] 2024-07-05 16:28:03.448860 run handler input out adu [00 C6 11 40 01 A3 00 09 00 B6 00 05 53 65 76 65 6E 00 ],galength is:18 subcom is [17 41] length is:50
1453[xx] 2024-07-05 16:28:03.448985 run handler input adu [00 C6 11 40 01 A3 00 09 00 B6 00 05 53 65 76 65 6E 00 ],count is:18 subcom is [17 41]1454 [xx] 2024-07-05 16:28:03.449011 gaserver head sn: 198

到此這篇關(guān)于golang切片拷貝的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)golang切片拷貝內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Golang實(shí)現(xiàn)CronJob(定時(shí)任務(wù))的方法詳解

    Golang實(shí)現(xiàn)CronJob(定時(shí)任務(wù))的方法詳解

    這篇文章主要為大家詳細(xì)介紹了Golang如何通過一個(gè)單 pod 去實(shí)現(xiàn)一個(gè)常駐服務(wù),去跑定時(shí)任務(wù)(CronJob),文中的示例代碼講解詳細(xì),需要的可以參考下
    2023-04-04
  • Golang多線程排序?qū)崿F(xiàn)快速高效地處理大規(guī)模數(shù)據(jù)

    Golang多線程排序?qū)崿F(xiàn)快速高效地處理大規(guī)模數(shù)據(jù)

    Golang多線程排序是一種快速高效地處理大規(guī)模數(shù)據(jù)的方法,通過使用Golang的協(xié)程和通道,可以將排序任務(wù)分配到多個(gè)線程中并行處理,提高了排序的效率和速度,需要詳細(xì)了解可以參考下文
    2023-05-05
  • Go語言使用ioutil.ReadAll函數(shù)需要注意基本說明

    Go語言使用ioutil.ReadAll函數(shù)需要注意基本說明

    這篇文章主要為大家介紹了Go語言使用ioutil.ReadAll函數(shù)需要注意基本說明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • 詳解Go并發(fā)編程時(shí)如何避免發(fā)生競態(tài)條件和數(shù)據(jù)競爭

    詳解Go并發(fā)編程時(shí)如何避免發(fā)生競態(tài)條件和數(shù)據(jù)競爭

    大家都知道,Go是一種支持并發(fā)編程的編程語言,但并發(fā)編程也是比較復(fù)雜和容易出錯(cuò)的。比如本篇分享的問題:競態(tài)條件和數(shù)據(jù)競爭的問題
    2023-04-04
  • go語言實(shí)現(xiàn)銀行卡號Luhn校驗(yàn)

    go語言實(shí)現(xiàn)銀行卡號Luhn校驗(yàn)

    這篇文章主要為大家介紹了go語言Luhn校驗(yàn)測試銀行卡號碼的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • Go語言中GORM存取數(shù)組/自定義類型數(shù)據(jù)

    Go語言中GORM存取數(shù)組/自定義類型數(shù)據(jù)

    在使用gorm時(shí)往往默認(rèn)的數(shù)據(jù)類型不滿足我們的要求,需要使用一些自定義數(shù)據(jù)類型作為字段類型,下面這篇文章主要給大家介紹了關(guān)于Go語言中GORM存取數(shù)組/自定義類型數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下
    2023-01-01
  • Go與C語言的互操作實(shí)現(xiàn)

    Go與C語言的互操作實(shí)現(xiàn)

    在Go與C語言互操作方面,Go更是提供了強(qiáng)大的支持。尤其是在Go中使用C,你甚至可以直接在Go源文件中編寫C代碼,本文就詳細(xì)的介紹一下如何使用,感興趣的可以了解一下
    2021-12-12
  • Go并發(fā)與鎖的兩種方式該如何提效詳解

    Go并發(fā)與鎖的兩種方式該如何提效詳解

    如果沒有鎖,在我們的項(xiàng)目中,可能會(huì)存在多個(gè)goroutine同時(shí)操作一個(gè)資源(臨界區(qū)),這種情況會(huì)發(fā)生競態(tài)問題(數(shù)據(jù)競態(tài)),下面這篇文章主要給大家介紹了關(guān)于Go并發(fā)與鎖的兩種方式該如何提效的相關(guān)資料,需要的朋友可以參考下
    2022-12-12
  • GoLang 中的隨機(jī)數(shù)的示例代碼

    GoLang 中的隨機(jī)數(shù)的示例代碼

    本篇文章主要介紹了GoLang 中的隨機(jī)數(shù)的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-03-03
  • 解決Golang map range遍歷結(jié)果不穩(wěn)定問題

    解決Golang map range遍歷結(jié)果不穩(wěn)定問題

    這篇文章主要介紹了解決Golang map range遍歷結(jié)果不穩(wěn)定問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12

最新評論