One, thread-safe classes
Package Safeslicetype Safeslice Chan commanddatatype commanddatastruct{Action Commandaction indexintItemInterface{} result chan<-Interface{} data chan<-[]Interface{} Updater Updatefunc}type commandactionintConst(Insert Commandaction=Iota Remove at update end length) type Updatefunc func (Interface{})Interface{}type SafesliceInterface{Append (Interface{})//Append The given item to the sliceat (int)Interface{}//Return the item at the given index positionClose () []Interface{}//Close the channel and return the sliceDelete (int)//Delete the item at the given index positionLen ()int //Return The number of items in the sliceUpdate (int, Updatefunc)//Update the item at the given index position}func New () safeslice {slice:=Make (Safeslice) go Slice.run ()returnSlice}func (Slice Safeslice) run () {list:= Make ([]Interface{},0) forCommand: =Range Slice {Switchcommand.action { Caseinsert:list=Append (list, command.item) CaseRemove//potentially expensive for long lists if 0<= Command.index && Command.index <len (list) {list=append (List[:command.index], List[command.index+1:]...) } CaseAt :if 0<= Command.index && Command.index <len (list) {Command.result<-List[command.index]}Else{Command.result<-Nil} CaseLength:command.result<-len (list) CaseUpdate:if 0<= Command.index && Command.index <len (list) {List[command.index]=Command.updater (List[command.index])} Caseend:close (slice) command.data<-List}}} Func (Slice safeslice) Append (itemInterface{}) {slice<-Commanddata{action:insert, Item:item}}func (Slice safeslice) Delete (Indexint) {Slice<-Commanddata{action:remove, Index:index}}func (Slice safeslice) at (Indexint)Interface{} {reply:= Make (chanInterface{}) Slice<-Commanddata{at, index, nil, reply, nil, nil}return<-Reply}func (Slice safeslice) Len ()int{reply:= Make (chanInterface{}) Slice<-commanddata{action:length, result:reply}return(<-reply). (int)}//If The Updater calls a Safeslice method we'll get deadlock!Func (Slice Safeslice) Update (indexint, Updater Updatefunc) {Slice<-commanddata{action:update, Index:index, Updater:updater}}func (Slice safeslice) Close () []Interface{} {reply:= Make (Chan []Interface{}) Slice<-commanddata{action:end, data:reply}return<-Reply}
This is a thread-safe slice that, on the surface, does not see any locks or mutexes, and so on, to achieve thread safety.
In fact, it should be said that an actor wearing a slice coat.
The whole implementation says this: Start a gorountin and give it a channel, and when you need to manipulate this slice point, encapsulate the information you want to manipulate into the command struct, then package the entire struct, From this channel to Gorountin, and then this "slice" ordered from Gorountin read to this command, according to command operation Information, command operation execution.
If the gorountin does not have buffers, then all operations are blocked, that is, if 1-5 of the 5 threads are to operate the slice sequentially, then the requests of the other threads are suspended until the first one is executed, and the second is executed sequentially until the first one finishes.
"Go Language Programming" study (IX)