doudun1029 2018-12-21 06:27
浏览 3
已采纳

切片周围的包装纸正在做奇怪的事情

I am probably wasting my time implementing this, but I am looking for a way to push/pop to a slice more easily, so I have this:

package h

import (
    "sync"
    log "github.com/sirupsen/logrus"
)

type List struct {
   internalList []interface{}
    mux sync.Mutex
}


func MakeList(l []interface{}) List{
    return List{l, sync.Mutex{}}
}


func (l List) Add(args ...interface{}) List{
    l.mux.Lock()
    l.internalList = append(l.internalList, args...)
    log.Info(l.internalList)
    l.mux.Unlock()
    return l;
}

func (l List) Push(v interface{}) List {
    l.mux.Lock()
    l.internalList = append(l.internalList, v)
    log.Info("internal:",l.internalList);
    l.mux.Unlock()
    return l;
}


func (l List) Pop() interface{}{
    l.mux.Lock()
    length :=len(l.internalList);
    log.Info("the length is:", length)
    if length < 1 {
        return nil;
    }
    last := l.internalList[length-1]
    l.internalList = l.internalList[:length-1]
    l.mux.Unlock()
    return last;
}

func (l List) GetLength() int {
    return len(l.internalList);
}

func (l List) Shift() interface{} {
    l.mux.Lock()
    if len(l.internalList) < 1 {
        return nil;
    }
    first := l.internalList[0];
    l.internalList = l.internalList[1:]
    l.mux.Unlock()
    return first;
}

func (l List) Unshift(v interface{}){
    l.mux.Lock()
    l.internalList = append([]interface{}{v}, l.internalList...)
    l.mux.Unlock()
}

func (l List) GetValue() []interface{}{
    return l.internalList
}

and then I use it like so:

package main

import (
    "github.com/sirupsen/logrus"
    "huru/h"
    "huru/utils"
)

func main(){

    x := h.List{}
    x.Push(3)
    logrus.Info("value:",x.GetValue())
    logrus.Info("len:",x.GetLength());
    logrus.Info(x.Pop());


}

but the weird thing is I get this:

INFO[0000] internal:[3]                                 
INFO[0000] value:[]                                     
INFO[0000] len:0                                        
INFO[0000] the length is:0                              
INFO[0000] <nil>        

I have no idea why 3 gets added to the slice, but then the slice length mysteriously goes to zero and when I pop() I get nil. Anybody know why that's happening?

Given the existing answer, I am wondering if there is a difference between:

func (l *List) Add(args ...interface{}) *List {
    l.mux.Lock()
    l.internalList = append(l.internalList, args...)
    log.Info(l.internalList)
    l.mux.Unlock()
    return l;
}

func (l *List) Push(v interface{}) *List {
    l.mux.Lock()
    l.internalList = append(l.internalList, v)
    log.Info("internal:",l.internalList)
    l.mux.Unlock()
    return l
}

and

func (l *List) Add(args ...interface{}) List {
    l.mux.Lock()
    l.internalList = append(l.internalList, args...)
    log.Info(l.internalList)
    l.mux.Unlock()
    return *l;
}

func (l *List) Push(v interface{}) List {
    l.mux.Lock()
    l.internalList = append(l.internalList, v)
    log.Info("internal:",l.internalList)
    l.mux.Unlock()
    return *l
}
  • 写回答

1条回答 默认 最新

  • duanqian3953 2018-12-21 06:34
    关注

    Since your methods are mutating the data, they need to use pointer receivers:

    func (l *List) Push(v interface{}) List {
        ...
    }
    

    Otherwise, the state will be updated on the copy of the struct, and lost after that.

    More on that in Effective Go

    Update: I noticed that you return the updated value from your methods. If the copy is what you actually want, you need to keep the value receivers as they are now, but then use the returned values in your calling code as well:

    x = x.Push(3)
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?