golang切片有浅拷贝和深拷贝的区别
去若是浅拷贝,原始的切片变化后所有的切片都会变化,无论切片是否在一个函数,还是一个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