GOLANG Delete a slice from Slice of Slice - go

I want to create function to delete a slice from slice of slice. It should take two inputs: 1. slice of slice (list var) and 2. slice to be deleted (eachsvc) as input. And return updated slice of slice (list var).
I am having issues with this code as it is not working with slice of slice. Any help is appreciated. Thanks.
func truncate_slice(list [][]string, eachsvc []string) [][]string {
//find index of eachsvc in list
i := indexOf(eachsvc, list)
copy(list[i:], list[i+1:]) // Shift a[i+1:] left one index.
list[len(list)-1] = "" // Erase last element (write zero value).
list = list[:len(list)-1] // Truncate slice.
return list
}
Func to get index of slice to be deleted from slice of slice
func indexOf(element []string, data [][]string) int {
for k, v := range data {
if element == v {
return k
}
}
return -1 //not found.
}

Since you want to compare slices based on their elements (as you commented), you will first need to define a function to check equality of 2 given slices. Something like this:
func eq(s1, s2 []string) bool {
if len(s1) != len(s2) {
return false
}
s2Map := make(map[string]int)
s1Map := make(map[string]int)
for _, str := range s2 {
s2Map[str] += 1
}
for _, str := range s1 {
s1Map[str] += 1
}
for key, count := range s1Map {
if count != s2Map[key] {
return false
}
}
return true
}
So in this case, ["John", "Doe"] is equal to ["Doe", "John"]. If you also want to check order, I would suggest you to use reflect.DeepEqual(slice1, slice2) instead of implementing one. By the way, using == to compare slices, means if they have the same reference, since slices are views over arrays basically.

As AminMal has said, you can use "reflect.DeepEqual(slice1, slice2)" to compare the slices.
As per documentation:
Slice values are deeply equal when all of the following are true: they are both nil or both non-nil, they have the same length, and either they point to the same initial entry of the same underlying array (that is, &x[0] == &y[0]) or their corresponding elements (up to length) are deeply equal. Note that a non-nil empty slice and a nil slice (for example, []byte{} and []byte(nil)) are not deeply equal.
package main
import (
"errors"
"fmt"
"reflect"
)
func main() {
sl := [][]string{[]string{"test1"}, []string{"test1", "test2"}, []string{"test3"}}
truncSlic, err := truncate_slice(sl, []string{"test3"})
if err != nil {
fmt.Println(err)
return
}
fmt.Println(truncSlic)
}
func indexOf(element []string, data [][]string) int {
for i, v := range data {
if reflect.DeepEqual(element, v) { //compare two silces
return i
}
}
return -1
}
func truncate_slice(list [][]string, eachsvc []string) ([][]string, error) {
//find index of eachsvc in list
i := indexOf(eachsvc, list)
if i == -1 {
return nil, errors.New("Not Found")
}
copy(list[i:], list[i+1:]) // Shift a[i+1:] left one index.
list[len(list)-1] = nil // Erase last element (write zero value).
list = list[:len(list)-1] // Truncate slice.
return list, nil
}
Output: [[test1] [test1 test2]]

element == v is invalid, because the operator == is not defined on []string, so you should define it:
func truncate_slice(list [][]string, eachsvc []string) [][]string {
//find index of eachsvc in list
i := indexOf(eachsvc, list)
copy(list[i:], list[i+1:]) // Shift a[i+1:] left one index.
list[len(list)-1] = nil // Erase last element (write zero value).
list = list[:len(list)-1] // Truncate slice.
return list
}
func indexOf(element []string, data [][]string) int {
for k, v := range data {
if equals(element, v) {
return k
}
}
return -1 //not found.
}
func equals(l1, l2 []string) bool {
if len(l1) != len(l2) {
return false
}
for i := 0; i < len(l1); i++ {
if l1[i] != l2[i] {
return false
}
}
return true
}

Related

Modifying receiver with a method on value?

package matrix
import (
"errors"
"strconv"
"strings"
)
// Matrix matrix inteface
type Matrix interface {
Rows() [][]int
Cols() [][]int
Set(r, c, val int) bool
}
// matrix implements the interface Matrix
type matrix struct {
data [][]int
rows int
cols int
}
// New returns a valid matrix created from the input
func New(input string) (Matrix, error) {
var m matrix
rows := strings.Split(input, "\n")
for r, row := range rows {
rowElements := strings.Fields(row)
switch {
case r == 0:
m.rows, m.cols = len(rows), len(rowElements)
matrix, err := allocateMemory(m.rows, m.cols)
if err != nil {
return invalidMatrix()
}
m.data = matrix
case len(rowElements) != m.cols:
return invalidMatrix()
}
for c, element := range rowElements {
element, err := strconv.Atoi(element)
if err != nil {
return invalidMatrix()
}
m.data[r][c] = element
}
}
return m, nil
}
// invalidMatrix returns the error indicating the
// provided matrix is invalid
func invalidMatrix() (Matrix, error) {
return nil, errors.New("invalid matrix")
}
// allocateMemory allocates a 2D slice of int having size RxC
func allocateMemory(R, C int) ([][]int, error) {
if R < 1 || C < 1 {
return nil, errors.New("invalid matrix")
}
matrix := make([][]int, R)
for r := range matrix {
matrix[r] = make([]int, C)
}
return matrix, nil
}
// Set sets the given value at (r,c) in the matrix,
// if (r,c) belongs to the matrix.
func (m matrix) Set(r, c, val int) bool {
switch {
case r < 0 || c < 0:
return false
case r >= m.rows || c >= m.cols:
return false
default:
m.data[r][c] = val
return true
}
}
// order defines the order the matrix to export
// two useful values are columnMajor and rowMajor
type order int
const (
columnMajor order = iota
rowMajor
)
// Cols returns columns of the matrix.
func (m matrix) Cols() [][]int {
return m.export(columnMajor)
}
// Rows returns rows of the matrix.
func (m matrix) Rows() [][]int {
return m.export(rowMajor)
}
// export return the matrix in the required order;
// either columnMajor or rowMajor.
func (m matrix) export(o order) [][]int {
var matrix [][]int
var err error
switch o {
case columnMajor:
matrix, err = allocateMemory(m.cols, m.rows)
if err != nil {
return nil
}
for r, row := range m.data {
for c, element := range row {
matrix[c][r] = element
}
}
case rowMajor:
matrix, err = allocateMemory(m.rows, m.cols)
if err != nil {
return nil
}
for r, row := range m.data {
copy(matrix[r], row)
}
}
return matrix
}
I am having a hard time understanding why the method Set() is able to modify the data of the struct. I had an understanding that methods defined on values cannot do that. I have tried to compare it with another problem where I cannot modify the content of receiver but in this case it just works. A test file for this code is available at test file. Any idea what I am missing?
The reason Set can modify the contents of the slice is that the slice is a reference value. Your other example (in the comment) attempts to assign the field holding the slice, and this won't work - because it's working on a copy. See this code sample:
package main
import (
"fmt"
)
type Holder struct {
s []int
v []int
}
func (h Holder) Set() {
// This will successfully modify the `s` slice's contents
h.s[0] = 99
// This will assign a new slice to a copy of the v field,
// so it won't affect the actual value on which this
// method is invoked.
h.v = []int{1, 2, 3}
}
func main() {
var h Holder
h.s = []int{10, 20, 30}
h.v = []int{40, 50, 60}
fmt.Println("before Set:", h)
h.Set()
fmt.Println("after Set:", h)
}
You can run it on the playground, and it prints:
before Set: {[10 20 30] [40 50 60]}
after Set: {[99 20 30] [40 50 60]}
What happens here is that even though Set gets a copy of h, and hence h.s is a copy too, but both copies point to the same underlying slice, so the contents can be modified. Read this post for all the details.
A slice value contains (ptr, len, cap) where ptr is a pointer to the slice's underlying array. The Set method modifies the slice's underlying array by dereferencing the pointer. The slice value, stored in the field, is not modified.
The Go Language blog post on slices describes the slice memory layout in more detail.

Code to generate powerset in Golang gives wrong result

Next code in Golang to generate powerset produces wrong result on input {"A", "B", "C", "D", "E"}. I see [A B C E E] as the last generated set.
package main
import (
"fmt"
)
func main() {
for _, s := range PowerSet([]string{"A", "B", "C", "D", "E"}) {
fmt.Println(s)
}
}
func PowerSet(set []string) [][]string {
var powerSet [][]string
powerSet = append(powerSet, make([]string, 0))
for _, element := range set {
var moreSets [][]string
for _, existingSet := range powerSet {
newSet := append(existingSet, element)
moreSets = append(moreSets, newSet)
}
powerSet = append(powerSet, moreSets...)
}
return powerSet
}
How to fix it? How to write it idiomatically in Go?
The problem with your program is not the algorithm itself but this line:
newSet := append(existingSet, element)
You should not append and assign to a different variable.
As the documentation states (emphasis mine), "The append built-in function appends elements to the end of a slice. If it has sufficient capacity, the destination is resliced to accommodate the new elements. If it does not, a new underlying array will be allocated.".
So, there might be cases where newSet := append(existingSet, element) will actually modify existingSet itself, which would break your logic.
If you change that to instead create a new array and append to that one, it works as you expect it.
newSet := make([]string, 0)
newSet = append(newSet, existingSet...)
newSet = append(newSet, element)
For instance, you can use algorithm like this one: https://stackoverflow.com/a/2779467/3805062.
func PowerSet(original []string) [][]string {
powerSetSize := int(math.Pow(2, float64(len(original))))
result := make([][]string, 0, powerSetSize)
var index int
for index < powerSetSize {
var subSet []string
for j, elem := range original {
if index& (1 << uint(j)) > 0 {
subSet = append(subSet, elem)
}
}
result = append(result, subSet)
index++
}
return result
}
Elaborating on #eugenioy's answer.
Look at this thread. Here is a working example : https://play.golang.org/p/dzoTk1kimf
func copy_and_append_string(slice []string, elem string) []string {
// wrong: return append(slice, elem)
return append(append([]string(nil), slice...), elem)
}
func PowerSet(s []string) [][]string {
if s == nil {
return nil
}
r := [][]string{[]string{}}
for _, es := range s {
var u [][]string
for _, er := range r {
u = append(u, copy_and_append_string(er, es))
}
r = append(r, u...)
}
return r
}

check for equality on slices without order

I am trying to find a solution to check for equality in 2 slices. Unfortanely, the answers I have found require values in the slice to be in the same order. For example, http://play.golang.org/p/yV0q1_u3xR evaluates equality to false.
I want a solution that lets []string{"a","b","c"} == []string{"b","a","c"} evaluate to true.
MORE EXAMPLES
[]string{"a","a","c"} == []string{"c","a","c"} >>> false
[]string{"z","z","x"} == []string{"x","z","z"} >>> true
Here is an alternate solution, though perhaps a bit verbose:
func sameStringSlice(x, y []string) bool {
if len(x) != len(y) {
return false
}
// create a map of string -> int
diff := make(map[string]int, len(x))
for _, _x := range x {
// 0 value for int is 0, so just increment a counter for the string
diff[_x]++
}
for _, _y := range y {
// If the string _y is not in diff bail out early
if _, ok := diff[_y]; !ok {
return false
}
diff[_y] -= 1
if diff[_y] == 0 {
delete(diff, _y)
}
}
return len(diff) == 0
}
Try it on the Go Playground
You can use cmp.Diff together with cmpopts.SortSlices:
less := func(a, b string) bool { return a < b }
equalIgnoreOrder := cmp.Diff(x, y, cmpopts.SortSlices(less)) == ""
Here is a full example that runs on the Go Playground:
package main
import (
"fmt"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
)
func main() {
x := []string{"a", "b", "c"}
y := []string{"a", "c", "b"}
less := func(a, b string) bool { return a < b }
equalIgnoreOrder := cmp.Diff(x, y, cmpopts.SortSlices(less)) == ""
fmt.Println(equalIgnoreOrder) // prints "true"
}
The other answers have better time complexity O(N) vs (O(N log(N)), that are in my answer, also my solution will take up more memory if elements in the slices are repeated frequently, but I wanted to add it because I think this is the most straight forward way to do it:
package main
import (
"fmt"
"sort"
"reflect"
)
func array_sorted_equal(a, b []string) bool {
if len(a) != len(b) {return false }
a_copy := make([]string, len(a))
b_copy := make([]string, len(b))
copy(a_copy, a)
copy(b_copy, b)
sort.Strings(a_copy)
sort.Strings(b_copy)
return reflect.DeepEqual(a_copy, b_copy)
}
func main() {
a := []string {"a", "a", "c"}
b := []string {"c", "a", "c"}
c := []string {"z","z","x"}
d := []string {"x","z","z"}
fmt.Println( array_sorted_equal(a, b))
fmt.Println( array_sorted_equal(c, d))
}
Result:
false
true
I would think the easiest way would be to map the elements in each array/slice to their number of occurrences, then compare the maps:
func main() {
x := []string{"a","b","c"}
y := []string{"c","b","a"}
xMap := make(map[string]int)
yMap := make(map[string]int)
for _, xElem := range x {
xMap[xElem]++
}
for _, yElem := range y {
yMap[yElem]++
}
for xMapKey, xMapVal := range xMap {
if yMap[xMapKey] != xMapVal {
return false
}
}
return true
}
You'll need to add some additional due dilligence, like short circuiting if your arrays/slices contain elements of different types or are of different length.
Generalizing the code of testify ElementsMatch, solution to compare any kind of objects (in the example []map[string]string):
https://play.golang.org/p/xUS2ngrUWUl
Like adrianlzt wrote in his answer, an implementation of assert.ElementsMatch from testify can be used to achieve that. But how about reusing actual testify module instead of copying that code when all you need is a bool result of the comparison? The implementation in testify is intended for tests code and usually takes testing.T argument.
It turns out that ElementsMatch can be quite easily used outside of testing code. All it takes is a dummy implementation of an interface with ErrorF method:
type dummyt struct{}
func (t dummyt) Errorf(string, ...interface{}) {}
func elementsMatch(listA, listB interface{}) bool {
return assert.ElementsMatch(dummyt{}, listA, listB)
}
Or test it on The Go Playground, which I've adapted from the adrianlzt's example.
Since I haven't got enough reputation to comment, I have to post yet another answer with a bit better code readability:
func AssertSameStringSlice(x, y []string) bool {
if len(x) != len(y) {
return false
}
itemAppearsTimes := make(map[string]int, len(x))
for _, i := range x {
itemAppearsTimes[i]++
}
for _, i := range y {
if _, ok := itemAppearsTimes[i]; !ok {
return false
}
itemAppearsTimes[i]--
if itemAppearsTimes[i] == 0 {
delete(itemAppearsTimes, i)
}
}
if len(itemAppearsTimes) == 0 {
return true
}
return false
}
The logic is the same as in this answer
I know its been answered but still I would like to add my answer. By following code here stretchr/testify we can have something like
func Elementsmatch(listA, listB []string) (string, bool) {
aLen := len(listA)
bLen := len(listB)
if aLen != bLen {
return fmt.Sprintf("Len of the lists don't match , len listA %v, len listB %v", aLen, bLen), false
}
visited := make([]bool, bLen)
for i := 0; i < aLen; i++ {
found := false
element := listA[i]
for j := 0; j < bLen; j++ {
if visited[j] {
continue
}
if element == listB[j] {
visited[j] = true
found = true
break
}
}
if !found {
return fmt.Sprintf("element %s appears more times in %s than in %s", element, listA, listB), false
}
}
return "", true
}
Now lets talk about performance of this solution compared to map based ones. Well it really depends on the size of the lists which you are comparing, If size of list is large (I would say greater than 20) then map approach is better else this would be sufficent.
Well on Go PlayGround it shows 0s always, but run this on local system and you can see the difference in time taken as size of list increases
So the solution I propose is, adding map based comparision from above solution
func Elementsmatch(listA, listB []string) (string, bool) {
aLen := len(listA)
bLen := len(listB)
if aLen != bLen {
return fmt.Sprintf("Len of the lists don't match , len listA %v, len listB %v", aLen, bLen), false
}
if aLen > 20 {
return elementsMatchByMap(listA, listB)
}else{
return elementsMatchByLoop(listA, listB)
}
}
func elementsMatchByLoop(listA, listB []string) (string, bool) {
aLen := len(listA)
bLen := len(listB)
visited := make([]bool, bLen)
for i := 0; i < aLen; i++ {
found := false
element := listA[i]
for j := 0; j < bLen; j++ {
if visited[j] {
continue
}
if element == listB[j] {
visited[j] = true
found = true
break
}
}
if !found {
return fmt.Sprintf("element %s appears more times in %s than in %s", element, listA, listB), false
}
}
return "", true
}
func elementsMatchByMap(x, y []string) (string, bool) {
// create a map of string -> int
diff := make(map[string]int, len(x))
for _, _x := range x {
// 0 value for int is 0, so just increment a counter for the string
diff[_x]++
}
for _, _y := range y {
// If the string _y is not in diff bail out early
if _, ok := diff[_y]; !ok {
return fmt.Sprintf(" %v is not present in list b", _y), false
}
diff[_y] -= 1
if diff[_y] == 0 {
delete(diff, _y)
}
}
if len(diff) == 0 {
return "", true
}
return "", false
}

How to check the uniqueness inside a for-loop?

Is there a way to check slices/maps for the presence of a value?
I would like to add a value to a slice only if it does not exist in the slice.
This works, but it seems verbose. Is there a better way to do this?
orgSlice := []int{1, 2, 3}
newSlice := []int{}
newInt := 2
newSlice = append(newSlice, newInt)
for _, v := range orgSlice {
if v != newInt {
newSlice = append(newSlice, v)
}
}
newSlice == [2 1 3]
Your approach would take linear time for each insertion. A better way would be to use a map[int]struct{}. Alternatively, you could also use a map[int]bool or something similar, but the empty struct{} has the advantage that it doesn't occupy any additional space. Therefore map[int]struct{} is a popular choice for a set of integers.
Example:
set := make(map[int]struct{})
set[1] = struct{}{}
set[2] = struct{}{}
set[1] = struct{}{}
// ...
for key := range(set) {
fmt.Println(key)
}
// each value will be printed only once, in no particular order
// you can use the ,ok idiom to check for existing keys
if _, ok := set[1]; ok {
fmt.Println("element found")
} else {
fmt.Println("element not found")
}
Most efficient is likely to be iterating over the slice and appending if you don't find it.
func AppendIfMissing(slice []int, i int) []int {
for _, ele := range slice {
if ele == i {
return slice
}
}
return append(slice, i)
}
It's simple and obvious and will be fast for small lists.
Further, it will always be faster than your current map-based solution. The map-based solution iterates over the whole slice no matter what; this solution returns immediately when it finds that the new value is already present. Both solutions compare elements as they iterate. (Each map assignment statement certainly does at least one map key comparison internally.) A map would only be useful if you could maintain it across many insertions. If you rebuild it on every insertion, then all advantage is lost.
If you truly need to efficiently handle large lists, consider maintaining the lists in sorted order. (I suspect the order doesn't matter to you because your first solution appended at the beginning of the list and your latest solution appends at the end.) If you always keep the lists sorted then you you can use the sort.Search function to do efficient binary insertions.
Another option:
package main
import "golang.org/x/tools/container/intsets"
func main() {
var (
a intsets.Sparse
b bool
)
b = a.Insert(9)
println(b) // true
b = a.Insert(9)
println(b) // false
}
https://pkg.go.dev/golang.org/x/tools/container/intsets
This option if the number of missing numbers is unknown
AppendIfMissing := func(sl []int, n ...int) []int {
cache := make(map[int]int)
for _, elem := range sl {
cache[elem] = elem
}
for _, elem := range n {
if _, ok := cache[elem]; !ok {
sl = append(sl, elem)
}
}
return sl
}
distincting a array of a struct :
func distinctObjects(objs []ObjectType) (distinctedObjs [] ObjectType){
var output []ObjectType
for i:= range objs{
if output==nil || len(output)==0{
output=append(output,objs[i])
} else {
founded:=false
for j:= range output{
if output[j].fieldname1==objs[i].fieldname1 && output[j].fieldname2==objs[i].fieldname2 &&......... {
founded=true
}
}
if !founded{
output=append(output,objs[i])
}
}
}
return output
}
where the struct here is something like :
type ObjectType struct {
fieldname1 string
fieldname2 string
.........
}
the object will distinct by checked fields here :
if output[j].fieldname1==objs[i].fieldname1 && output[j].fieldname2==objs[i].fieldname2 &&......... {

Is there a foreach loop in Go?

Is there a foreach construct in the Go language?
Can I iterate over a slice or array using a for?
From For statements with range clause:
A "for" statement with a "range" clause iterates through all entries
of an array, slice, string or map, or values received on a channel.
For each entry it assigns iteration values to corresponding iteration
variables and then executes the block.
As an example:
for index, element := range someSlice {
// index is the index where we are
// element is the element from someSlice for where we are
}
If you don't care about the index, you can use _:
for _, element := range someSlice {
// element is the element from someSlice for where we are
}
The underscore, _, is the blank identifier, an anonymous placeholder.
Go has a foreach-like syntax. It supports arrays/slices, maps and channels.
Iterate over an array or a slice:
// index and value
for i, v := range slice {}
// index only
for i := range slice {}
// value only
for _, v := range slice {}
Iterate over a map:
// key and value
for key, value := range theMap {}
// key only
for key := range theMap {}
// value only
for _, value := range theMap {}
Iterate over a channel:
for v := range theChan {}
Iterating over a channel is equivalent to receiving from a channel until it is closed:
for {
v, ok := <-theChan
if !ok {
break
}
}
Following is the example code for how to use foreach in Go:
package main
import (
"fmt"
)
func main() {
arrayOne := [3]string{"Apple", "Mango", "Banana"}
for index,element := range arrayOne{
fmt.Println(index)
fmt.Println(element)
}
}
This is a running example https://play.golang.org/p/LXptmH4X_0
Yes, range:
The range form of the for loop iterates over a slice or map.
When ranging over a slice, two values are returned for each iteration. The first is the index, and the second is a copy of the element at that index.
Example:
package main
import "fmt"
var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}
func main() {
for i, v := range pow {
fmt.Printf("2**%d = %d\n", i, v)
}
for i := range pow {
pow[i] = 1 << uint(i) // == 2**i
}
for _, value := range pow {
fmt.Printf("%d\n", value)
}
}
You can skip the index or value by assigning to _.
If you only want the index, drop the , value entirely.
The following example shows how to use the range operator in a for loop to implement a foreach loop.
func PrintXml (out io.Writer, value interface{}) error {
var data []byte
var err error
for _, action := range []func() {
func () { data, err = xml.MarshalIndent(value, "", " ") },
func () { _, err = out.Write([]byte(xml.Header)) },
func () { _, err = out.Write(data) },
func () { _, err = out.Write([]byte("\n")) }} {
action();
if err != nil {
return err
}
}
return nil;
}
The example iterates over an array of functions to unify the error handling for the functions. A complete example is at Google´s playground.
PS: it shows also that hanging braces are a bad idea for the readability of code. Hint: the for condition ends just before the action() call. Obvious, isn't it?
You can in fact use range without referencing its return values by using for range against your type:
arr := make([]uint8, 5)
i,j := 0,0
for range arr {
fmt.Println("Array Loop", i)
i++
}
for range "bytes" {
fmt.Println("String Loop", j)
j++
}
https://play.golang.org/p/XHrHLbJMEd
This may be obvious, but you can inline the array like so:
package main
import (
"fmt"
)
func main() {
for _, element := range [3]string{"a", "b", "c"} {
fmt.Print(element)
}
}
outputs:
abc
https://play.golang.org/p/gkKgF3y5nmt
I'm seeing a lot of examples using range. Just a heads up that range creates a copy of whatever you're iterating over. If you make changes to the contents in a foreach range you will not be changing the values in the original container, in that case you'll need a traditional for loop with an index you increment and deference indexed reference. E.g.:
for i := 0; i < len(arr); i++ {
element := &arr[i]
element.Val = newVal
}
I have just implemented this library: https://github.com/jose78/go-collection.
This is an example of how to use the Foreach loop:
package main
import (
"fmt"
col "github.com/jose78/go-collection/collections"
)
type user struct {
name string
age int
id int
}
func main() {
newList := col.ListType{user{"Alvaro", 6, 1}, user{"Sofia", 3, 2}}
newList = append(newList, user{"Mon", 0, 3})
newList.Foreach(simpleLoop)
if err := newList.Foreach(simpleLoopWithError); err != nil{
fmt.Printf("This error >>> %v <<< was produced", err )
}
}
var simpleLoop col.FnForeachList = func(mapper interface{}, index int) {
fmt.Printf("%d.- item:%v\n", index, mapper)
}
var simpleLoopWithError col.FnForeachList = func(mapper interface{}, index int) {
if index > 1{
panic(fmt.Sprintf("Error produced with index == %d\n", index))
}
fmt.Printf("%d.- item:%v\n", index, mapper)
}
The result of this execution should be:
0.- item:{Alvaro 6 1}
1.- item:{Sofia 3 2}
2.- item:{Mon 0 3}
0.- item:{Alvaro 6 1}
1.- item:{Sofia 3 2}
Recovered in f Error produced with index == 2
ERROR: Error produced with index == 2
This error >>> Error produced with index == 2
<<< was produced
Try this code in playGrounD.

Resources