当前位置: 代码网 > it编程>前端脚本>Golang > golang切片拷贝的实现

golang切片拷贝的实现

2024年11月03日 Golang 我要评论
golang切片有浅拷贝和深拷贝的区别1、深拷贝(deep copy)拷贝的是数据本身,创造一个样的新对象,新创建的对象与原对象不共享内存,新创建的对象在内存中开辟一个新的内存地址,新对象值修改时不会

golang切片有浅拷贝和深拷贝的区别

1、深拷贝(deep copy)

拷贝的是数据本身,创造一个样的新对象,新创建的对象与原对象不共享内存,新创建的对象在内存中开辟一个新的内存地址,新对象值修改时不会影响原对象值。既然内存地址不同,释放内存地址时,可分别释放。

值类型的数据,默认全部都是深复制,array、int、string、struct、float,bool。

2、浅拷贝(shallow copy)

拷贝的是数据地址,只复制指向的对象的指针,此时新对象和老对象指向的内存地址是一样的,新对象值修改时老对象也会变化。释放内存地址时,同时释放内存地址。

引用类型的数据,默认全部都是浅复制,slice,map。

去若是浅拷贝,原始的切片变化后所有的切片都会变化,无论切片是否在一个函数,还是一个goroutine中,都会发生变化

如下代码为例子

package main

import "fmt"

func main() {
	
	// 创建一个切片
	originalslice := []int{1, 2, 3, 4, 5}

	// 使用切片[:]操作符创建浅拷贝
	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)
}

如下代码问题困扰了好久,才发现是切片赋值的问题

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)
	//可能一次读出来多个数据包 增加处理方式 @20240704
	//直接在for循环中使用
	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)
		///此处经常出现问题
		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
}

出现非常奇怪的问题切片内容经常莫名奇妙的改变,最后发现是切片赋值的问题

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

到此这篇关于golang切片拷贝的实现的文章就介绍到这了,更多相关golang切片拷贝内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com