SoFunction
Updated on 2025-03-02

Implementation of golang slice copy

Golang slices have the difference between shallow copy and deep copy

1. Deep Copy

What is copied is the data itself, creating a new object. The newly created object does not share memory with the original object. The newly created object opens a new memory address in the memory. The new object value will not affect the original object value when it is modified. Since the memory addresses are different, they can be released separately when the memory addresses are released.

All data of value type are copied by default, such as Array, Int, String, Struct, Float, and Bool.

2. Shallow Copy

The copy is the data address, and only the pointer to the object is copied. At this time, the memory address pointed to by the new object and the old object are the same. The old object will also change when the new object value is modified. When the memory address is released, the memory address is released at the same time.

Reference types of data, all by default are shallow copy, Slice, and Map.

If it is a shallow copy, all slices will change after the original slice changes, regardless of whether the slice is in a function or a goroutine.

The following code is an example

package main

import "fmt"

func main() {
	
	// Create a slice	originalSlice := []int{1, 2, 3, 4, 5}

	// Create shallow copy using the slice[:] operator	shallowCopy := originalSlice[:]
	shallowCopy2 := make([]int, len(shallowCopy))
	copy(shallowCopy2, originalSlice)

	// Modify the element of the original slice	originalSlice[0] = 100

	// Output original slices and shallow copies of slices	("Original Slice:", originalSlice)
	("Shallow Copy:", shallowCopy)
	("Shallow Copy2:", shallowCopy2)
}

The following code problem has been plagued by a long time before I found out that it is a problem with slice assignment

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

	defer func() {
		()

	}()
	go ()

	raw := make([]byte, tcpAduMaxSize)

	for {
		select {
		case <-():
			err = ("server active close")
			(err)
			return
		default:
		}

		err = (().Add())
		if err != nil {
			("set read tcp data time deadline error:", err)
		}
		count, err := (raw)

		if err != nil {
			if err !=  && err !=  || ((), "use of closed network connection") {
				return
			}

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

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

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

	}
}

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

		}
	}
}
func (sf *ServerSession) prerunhandler(prodata *ProcessData) {
	length := 
	adu := make([]byte, len())
	copy(adu, )
	subcom := 
	("run handler input1 out1 adu [% X] length is:%d\n", adu, length)
	//Maybe multiple data packets can be read out at once. Add processing method @20240704	//Use directly in the for loop	for length > 0 {
		headdata := adu[:gaHeaderSize]
		head1 := new(gadataHeader)
		buf1 := (headdata)
		err := (buf1, , head1)
		if err != nil {
			("ga server decode errr:", err)
		}
		("pre process packect SN:", )
		galength := int() + gaHeaderSize

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

		} else {
			("data length is %d, adu length is:%d\n", , len(adu))
			break
		}

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

	if !Find(subcom, ) {
		("subcom: %d is not in array %d \n", , subcom)
		return
	}
	// check head ProtocolIdentifier
	// if .Uint16(adu[2:]) != tcpProtocolIdentifier {
	// 	rdCnt, length = 0, tcpHeaderMbapSize
	// 	continue
	// }
	length := int() + gaHeaderSize
	if count == length {
		("start decode packet SN is:%d subcom is %d data length is:%d\n", , , )
		if err = (adu); err != nil {
			("gaserver decode error:", err)
			return
		}
	} else {
		("head data length: %d is not right %d \n", , count)
		///There are frequent problems here		("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
}

Very strange problems occur. Slice content often changes inexplicably, and finally it is found that it is a problem with slice assignment.

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

This is the end of this article about the implementation of golang slice copy. For more related golang slice copy content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!