Golang container/list creating a FindAll function - go

I was wondering if this is the way to create and pass 'generic'(yeah I know, a sensitive word in GoLang) lists to a FindAll function.
Here's my attempt:
package main
import (
"container/list"
"fmt"
"strings"
)
func FindAll(lst *list.List, p func(interface{}) bool) *list.List {
ans := list.New()
for i := lst.Front(); i != nil; i = i.Next() {
if p(i.Value) {
ans.PushBack(i.Value)
}
}
return ans
}
func ConvertToInt(p func(int) bool) func(interface{}) bool {
return func(v interface{}) bool {
if value, ok := v.(int); ok {
if p(value) {
return true
} else {
return false
}
} else {
return false
}
}
}
func IsEven(n int) bool {
if n%2 == 0 {
return true
}
return false
}
func ConvertoString(p func(s string) bool) func(interface{}) bool {
return func(v interface{}) bool {
if value, ok := v.(string); ok {
if p(value) {
return true
} else {
return false
}
} else {
return false
}
}
}
func IsHello(str string) bool {
if strings.ToLower(str) == "hello" {
return true
} else {
return false
}
}
func main() {
fmt.Println("Find All Programs!\n\n")
lsti := list.New()
for i := 0; i < 11; i++ {
lsti.PushBack(i)
}
ansIsEven := FindAll(lsti, ConvertToInt(IsEven))
for i := ansIsEven.Front(); i != nil; i = i.Next() {
if value, ok := i.Value.(int); ok {
fmt.Printf("Found even: %d\n", value)
} else {
fmt.Println("Huh! What's that?")
}
}
}
I've been playing with this for a while and thought I'd better get the advice of the Go experts before I convince myself its correct.

The code as-is is pretty fine, but you should ask your self 2 questions:
1. Why shouldn't you use a typed slice? (interface{} performance is slow compared to the explicit type, although it will greatly improve in Go 1.7)
2. Would it be better to implement your specific type as a linked list?
Something like this can be much more efficient:
type IntList []int
func (l IntList) Filter(fn func(v int) bool) IntList {
var o IntList
for _, v := range l {
if fn(v) {
o = append(o, v)
}
}
return o
}
There's almost always a better alternative to container/list, however it all depends on your use case.

Related

How to check if an element exists in linked list

I am trying to find if an element exists in my linked list so that duplicate elements are not added.
My code follows playground:
package main
import "fmt"
func (e Ensemble) EstVide() bool {
return e.ensemble == nil
}
func (e Ensemble) Card() int {
return e.longueur
}
type Cellule struct {
elem int
suivant *Cellule
}
type Ensemble struct {
ensemble *Cellule
longueur int
}
func (c Cellule) String() string {
if c.suivant == nil {
return fmt.Sprintf("%v}", c.elem)
}
return fmt.Sprintf("%v", c.elem)
}
func (e Ensemble) String() string {
if e.EstVide() {
return ""
}
res := "{"
for curr := e.ensemble; curr != nil; curr = curr.suivant {
res += fmt.Sprintf("%s ", curr)
}
return res[:len(res)-1]
}
func (e Ensemble) Appartient(valeur int) bool {
body := e.String()
for i := 0; i < e.Card(); i++ {
if valeur == int(body[i]) {
return true
}
}
return false
}
func (e *Ensemble) Ajouter(valeur int) {
if !e.Appartient(valeur) {
e.ensemble = &Cellule{elem: valeur, suivant: e.ensemble}
e.longueur++
}
}
func main() {
monEns := Ensemble{}
fmt.Printf("Nb d'éléments dans monEns %v\n", monEns.Card())
fmt.Printf("monEns = %v\n", monEns)
monEns.Ajouter(42)
monEns.Ajouter(10)
monEns.Ajouter(20)
monEns.Ajouter(10)
fmt.Printf("Nb d'éléments dans monEns %v\n", monEns.Card())
fmt.Printf("monEns = %v \n", monEns)
}
The output ({10 20 10 42} includes a duplicate element (10). How can I prevent this?

Data race occurs even if using sync.Mutex in map

How can I solve data race bug in this piece of code? I get an error in processPbxQueueByUniqueID func on l.Remove(frontItem). Do I need to maybe create another struct that contains sync.Mutex and *list.List and then change pbxQueueUniqueIDProcessor.processes to map[string]NewStructWithMutexAndList?
var pbxQueueUnique = newPbxQueueUniqueIDProcessor()
var pbxMutex sync.Mutex
type pbxQueueUniqueIDProcessor struct {
processes map[string]*list.List
}
func newPbxQueueUniqueIDProcessor() *pbxQueueUniqueIDProcessor {
return &pbxQueueUniqueIDProcessor{processes: make(map[string]*list.List)}
}
func (q *pbxQueueUniqueIDProcessor) Add(uniqueID string, item pbxQueueItem) {
pbxMutex.Lock()
defer pbxMutex.Unlock()
_, ok := q.processes[uniqueID]
if !ok {
l := &list.List{}
l.PushBack(item)
q.processes[uniqueID] = l
go processPbxQueueByUniqueID(uniqueID)
return
}
q.processes[uniqueID].PushBack(item)
}
func (q *pbxQueueUniqueIDProcessor) Get(uniqueID string) *list.List {
pbxMutex.Lock()
defer pbxMutex.Unlock()
return q.processes[uniqueID]
}
func (q *pbxQueueUniqueIDProcessor) RemoveFromList(uniqueID string, el *list.Element) {
pbxMutex.Lock()
defer pbxMutex.Unlock()
l := q.processes[uniqueID]
if l == nil {
return
}
l.Remove(el)
}
func processPbxQueueByUniqueID(uniqueID string) {
l := pbxQueueUnique.Get(uniqueID)
if l == nil {
return
}
for {
frontItem := l.Front()
if frontItem == nil {
break
}
frontValue := frontItem.Value.(pbxQueueItem)
execAcc(frontValue)
l.Remove(frontItem)
}
}

Prettify ugly three nested for-loop

What would be the most Go way of prettifying this function?
This is what I have come up with, kind of does the trick but It's just too ugly, any help on prettifying this would be greatly appreciated.
Also wold love to be able to negate this functions as well if possible.
Could I not utilise the use of function literals, maps etc.
var UsageTypes = []string{
"PHYSICAL_SIZE",
"PHYSICAL_SIZE",
"PROVISIONED_SIZE",
"SNAPSHOT_SIZE",
"LOGICAL_SIZE_PERCENTAGE",
"TOTAL_VOLUME_SIZE",
"ALLOCATED_SIZE",
"ALLOCATED_USED",
"TOTAL_LOGICAL_SIZE",
"TOTAL_LOGICAL_SIZE_PERCENTAGE",
"TOTAL_SNAPSHOT_SIZE",
"LOGICAL_OR_ALLOCATED_GREATER_SIZE",
}
var MeasuredTypes = []string{
"LIF_RECEIVED_DATA",
"ECEIVED_ERRORS",
"LIF_RECEIVED_PACKET",
"LIF_SENT_DATA",
"LIF_SENT_ERRORS",
"LIF_SENT_PACKET",
"LINK_CURRENT_STATE",
"RX_BYTES",
"RX_DISCARDS",
"RX_CRC_ERRORS",
"RX_ERRORS",
"RX_FRAMES",
"LINK_UP_TO_DOWNS",
"TX_BYTES",
"TX_DISCARDS",
"TX_ERRORS",
"TX_HW_ERRORS",
"TX_FRAMES",
"LOGICAL_OR_ALLOCATED_GREATER_SIZE",
"LOGICAL_SIZE",
"PHYSICAL_SIZE",
"PROVISIONED_SIZE",
"SNAPSHOT_SIZE",
"VOLUME_ONLINE",
"TOTAL_THROUGHPUT",
"LOGICAL_SIZE_PERCENTAGE",
"READ_THROUGHPUT",
"WRITE_THROUGHPUT",
"OTHER_THROUGHPUT",
"TOTAL_IOPS",
"WRITE_IOPS",
"READ_IOPS",
"OTHER_IOPS",
"AVERAGE_TOTAL_LATENCY",
"AVERAGE_WRITE_LATENCY",
"AVERAGE_READ_LATENCY",
"AVERAGE_OTHER_LATENCY",
"FILESYSTEM_READ_OPS",
"FILESYSTEM_WRITE_OPS",
"FILESYSTEM_TOTAL_OPS",
"FILESYSTEM_OTHER_OPS",
"IO_BYTES_PER_READ_OPS",
"IO_BYTES_PER_WRITE_OPS",
"IO_BYTES_PER_OTHER_OPS",
"IO_BYTES_PER_TOTAL_OPS",
"READ_IO",
"WRITE_IO",
"TOTAL_IO",
"OTHER_IO",
"ACTIVE_CONNECTIONS",
"TOTAL_VOLUME_SIZE",
"ALLOCATED_SIZE",
"ALLOCATED_USED",
"TOTAL_LOGICAL_SIZE",
"TOTAL_LOGICAL_SIZE_PERCENTAGE",
"TOTAL_SNAPSHOT_SIZE",
"ONTAP_CAPACITY_DISK_CAPACITY",
"ONTAP_CAPACITY_TOTAL_STORAGE_EFFICIENCY_RATIO",
"ONTAP_CAPACITY_TOTAL_PHYSICAL_USED",
"ONTAP_CAPACITY_SIZE_USED",
"ONTAP_CAPACITY_MEMORY",
"ONTAP_CAPACITY_AVERAGE_PROCESSOR_BUSY",
"ONTAP_CAPACITY_PEAK_PROCESSOR_BUSY",
}
func isMeasuredTypeAUsageMetric(measuredTypeIn []string) []string {
result := []string{}
for i, _ := range measuredTypeIn {
var foundInBigList bool
for j, _ := range MeasuredTypes {
if measuredTypeIn[i] == MeasuredTypes[j] {
foundInBigList = true
fmt.Println("found in big list: ", measuredTypeIn[i])
for k, _ := range UsageTypes {
if measuredTypeIn[i] == UsageTypes[k] {
fmt.Println("found in inner list: ", measuredTypeIn[i])
result = append(result, measuredTypeIn[i])
}
}
}
}
if foundInBigList == false {
fmt.Println("not found, throw exception")
}
}
return result
}
func main() {
measuredTypeIn := []string{"LOGICAL_SIZE_PERCENTAGE", "LOGICAL_OR_ALLOCATED_GREATER_SIZE", "BUKK", "ONTAP_CAPACITY_PEAK_PROCESSOR_BUSY",}
fmt.Println(isMeasuredTypeAUsageMetric(measuredTypeIn))
}
Right level of abstraction is what you need:
func has(in string[], item string) bool {
for _,x:=range in {
if x==item {
return true
}
}
return false
}
func isMeasuredTypeAUsageMetric(measuredTypeIn []string) []string {
result:=[]string{}
for _,item:=range measuredTypeIn {
if has(MeasuredTypes,item) {
if has(UsageTypes,item) {
result=append(result,item)
}
} else {
///error
}
}
return result
}
This can be further simplified by using a map[string]bool instead of a []string for the literals.
var MeasuredTypes=map[string]bool{"itemInUsageTypes": true,
"itemNotInUsageTypes":false,
...
}
Then you can do:
usage,measured:=MeasuredTypes[item]
if measured {
// It is measured type
if usage {
// It is usage type
}
}

How to check if all fields of a *struct are nil?

I'm not quite sure how to address this question, please feel free to edit.
With the first code block below, I am able to check if a all fields of a struct are nil.
In reality however, the values injected in the struct, are received as args.Review (see second code block below).
In the second code block, how can I check if all fields from args.Review are nil?
Try it on Golang Playground
package main
import (
"fmt"
"reflect"
)
type review struct {
Stars *int32 `json:"stars" bson:"stars,omitempty" `
Commentary *string `json:"commentary" bson:"commentary,omitempty"`
}
func main() {
newReview := &review{
Stars: nil,
// Stars: func(i int32) *int32 { return &i }(5),
Commentary: nil,
// Commentary: func(i string) *string { return &i }("Great"),
}
if reflect.DeepEqual(review{}, *newReview) {
fmt.Println("Nothing")
} else {
fmt.Println("Hello")
}
}
Try the second code on Golang Playground
This code below gets two errors:
prog.go:32:14: type args is not an expression
prog.go:44:27: args.Review is not a type
package main
import (
"fmt"
"reflect"
)
type review struct {
Stars *int32 `json:"stars" bson:"stars,omitempty" `
Commentary *string `json:"commentary" bson:"commentary,omitempty"`
}
type reviewInput struct {
Stars *int32
Commentary *string
}
type args struct {
PostSlug string
Review *reviewInput
}
func main() {
f := &args {
PostSlug: "second-post",
Review: &reviewInput{
Stars: func(i int32) *int32 { return &i }(5),
Commentary: func(i string) *string { return &i }("Great"),
},
}
createReview(args)
}
func createReview(args *struct {
PostSlug string
Review *reviewInput
}) {
g := &review{
Stars: args.Review.Stars,
Commentary: args.Review.Commentary,
}
if reflect.DeepEqual(args.Review{}, nil) {
fmt.Println("Nothing")
} else {
fmt.Println("Something")
}
}
If you're dealing with a small number of fields you should use simple if statements to determine whether they are nil or not.
if args.Stars == nil && args.Commentary == nil {
// ...
}
If you're dealing with more fields than you would like to manually spell out in if statements you could use a simple helper function that takes a variadic number of interface{} arguments. Just keep in mind that there is this: Check for nil and nil interface in Go
func AllNil(vv ...interface{}) bool {
for _, v := range vv {
if v == nil {
continue
}
if rv := reflect.ValueOf(v); !rv.IsNil() {
return false
}
}
return true
}
if AllNil(args.Stars, args.Commentary, args.Foo, args.Bar, args.Baz) {
// ...
}
Or you can use the reflect package to do your bidding.
func NilFields(x interface{}) bool {
rv := reflect.ValueOf(args)
rv = rv.Elem()
for i := 0; i < rv.NumField(); i++ {
if f := rv.Field(i); f.IsValid() && !f.IsNil() {
return false
}
}
return true
}
if NilFields(args) {
// ...
}

How can I compare struct data and interface data in Golang?

I am trying to create a generic Binary Tree in Golang. How can I compare data from an interface and input data in the code? Here is an example of what I am trying to do. The comparison that is giving me trouble is this
} else if cur.data < data {
-
package DSAA
type TreeNode struct {
data interface{}
right *TreeNode
left *TreeNode
}
type BinarySearchTree struct {
root *TreeNode
}
func BSTCreate() *BinarySearchTree {
return &BinarySearchTree{nil}
}
func (b *BinarySearchTree) Insert(cur TreeNode, data interface{}) *BinarySearchTree {
if &cur == nil {
cur := &TreeNode{data, nil, nil}
} else if cur.data < data {
b = b.Insert(*cur.left, data)
} else {
b = b.Insert(*cur.right, data)
}
return b
}
You have some options:
1- Using runtime type switch:
package main
import (
"fmt"
)
func main() {
fmt.Println(Less(1, 2)) // true
fmt.Println(Less("AB", "AC")) // true
}
func Less(a, b interface{}) bool {
switch v := a.(type) {
case int:
w := b.(int)
return v < w
case string:
w := b.(string)
return v < w
}
return false
}
then replace } else if cur.data < data { with
} else if Less(cur.data , data) {
2- Using Comparer interface:
package main
import (
"fmt"
)
type Comparer interface {
// Less reports whether the element is less than b
Less(b interface{}) bool
}
func main() {
a, b := Int(1), Int(2)
fmt.Println(a.Less(b)) // true
c, d := St("A"), St("B")
fmt.Println(c.Less(d)) // true
}
type Int int
func (t Int) Less(b interface{}) bool {
if v, ok := b.(Int); ok {
return int(t) < int(v)
}
return false
}
type St string
func (t St) Less(b interface{}) bool {
if v, ok := b.(St); ok {
return string(t) < string(v)
}
return false
}
3- Using reflect

Resources