I'm struggling with updating a slice inside map rulesByCountry without any success.
The value of enabled changes only inside the function UpdateName but the map itself still sees this value unchanged. I assume it's something to do with pointers. I guess I did not grasp the concept of it. Can someone direct me what I'm doing wrong here? I tried a lot of things and run out of options. I would appreciate any kind of help.
import (
"fmt"
)
// Consts
const RuleSeparateStreetNameFromHome string = "Separate street number from home"
// Types
type Address struct {
AddressLines []string
Country string
}
type RuleChain []RuleDefinition
type RuleDefinition struct {
Name string
Enabled bool
}
//Map
var rulesByCountry map[string][]RuleDefinition = map[string][]RuleDefinition{
"DE": {
{
Name: RuleSeparateStreetNameFromHome,
// TODO some logic,
Enabled: false,
},
},
}
func main() {
var addr *Address
addr = &Address{
AddressLines: []string{
"Street3",
},
Country: "DE",
}
rules := GetRulesForCountry(addr.GetCountry())
rules.UpdateName(RuleSeparateStreetNameFromHome)
fmt.Println(rules)
}
func GetRulesForCountry(country string) RuleChain {
if rules, ok := rulesByCountry[country]; ok {
return rules
}
return nil
}
func (a *Address) GetFirstAddressLine() string {
return a.GetAddressLine(1)
}
func (a *Address) GetAddressLine(lineNumber int) string {
if lineNumber <= 0 {
return ""
}
lines := a.GetAddressLines()
if len(lines) >= lineNumber {
return lines[lineNumber-1]
}
return ""
}
func (m *Address) GetAddressLines() []string {
if m != nil {
return m.AddressLines
}
return nil
}
func (r *RuleChain) UpdateName(name string) {
for _, rule := range *r {
if rule.Name == name {
rule.Enabled = true
fmt.Print(rule)
}
}
}
func (m *Address) GetCountry() string {
if m != nil {
return m.Country
}
return ""
}
Based on the inputs of mkopriva
package main
import (
"fmt"
)
// Consts
const RuleSeparateStreetNameFromHome string = "Separate street number from home"
// Types
type Address struct {
AddressLines []string
Country string
}
type RuleChain []*RuleDefinition
type RuleDefinition struct {
Name string
Enabled bool
}
//Map
var rulesByCountry map[string][]*RuleDefinition = map[string][]*RuleDefinition{
"DE": {
{
Name: RuleSeparateStreetNameFromHome,
// TODO some logic,
Enabled: false,
},
},
}
func main() {
var addr *Address
addr = &Address{
AddressLines: []string{
"Street3",
},
Country: "DE",
}
rules := GetRulesForCountry(addr.GetCountry())
rules.UpdateName(RuleSeparateStreetNameFromHome)
fmt.Println(rules[0])
}
func GetRulesForCountry(country string) RuleChain {
if rules, ok := rulesByCountry[country]; ok {
return rules
}
return nil
}
func (a *Address) GetFirstAddressLine() string {
return a.GetAddressLine(1)
}
func (a *Address) GetAddressLine(lineNumber int) string {
if lineNumber <= 0 {
return ""
}
lines := a.GetAddressLines()
if len(lines) >= lineNumber {
return lines[lineNumber-1]
}
return ""
}
func (m *Address) GetAddressLines() []string {
if m != nil {
return m.AddressLines
}
return nil
}
func (r *RuleChain) UpdateName(name string) {
for _, rule := range *r {
if rule.Name == name {
rule.Enabled = true
fmt.Print(rule)
}
}
}
func (m *Address) GetCountry() string {
if m != nil {
return m.Country
}
return ""
}
Output:
&{Separate street number from home true}&{Separate street number from home true}
Related
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?
Community,
The mission
basic
Implement a func that patches all string fields on an objects
details
[done] fields shall only be patched if they match a matcher func
[done] value shall be processed via process func
patching shall be done recursive
it shall also work for []string, []*string and recursive for structs and []struct, []*struct
// update - removed old code
Solution
structs
updated the structs to use (though this does not affect the actual program, i use this for completeness
type Tag struct {
Name string `process:"yes,TagName"`
NamePtr *string `process:"no,TagNamePtr"`
}
type User struct {
ID int
Nick string
Name string `process:"yes,UserName"`
NamePtr *string `process:"yes,UserNamePtr"`
Slice []string `process:"yes,Slice"`
SlicePtr []*string `process:"yes,SlicePtr"`
SubStruct []Tag `process:"yes,SubStruct"`
SubStructPtr []*Tag `process:"yes,SubStructPtr"`
}
helper func
Further we need two helper funcs to check if a struct has a tag and to print to console
func Stringify(i interface{}) string {
s, _ := json.MarshalIndent(i, "", " ")
return string(s)
}
func HasTag(structFiled reflect.StructField, tagName string, tagValue string) bool {
tag := structFiled.Tag
if value, ok := tag.Lookup(tagName); ok {
parts := strings.Split(value, ",")
if len(parts) > 0 {
return parts[0] == tagValue
}
}
return false
}
patcher - the actual solution
type Patcher struct {
Matcher func(structFiled *reflect.StructField, v reflect.Value) bool
Process func(in string) string
}
func (p *Patcher) value(idx int, v reflect.Value, structFiled *reflect.StructField) {
if !v.IsValid() {
return
}
switch v.Kind() {
case reflect.Ptr:
p.value(idx, v.Elem(), structFiled)
case reflect.Struct:
for i := 0; i < v.NumField(); i++ {
var sf = v.Type().Field(i)
structFiled = &sf
p.value(i, v.Field(i), structFiled)
}
case reflect.Slice:
for i := 0; i < v.Len(); i++ {
p.value(i, v.Index(i), structFiled)
}
case reflect.String:
if p.Matcher(structFiled, v) {
v.SetString(p.Process(v.String()))
}
}
}
func (p *Patcher) Apply(in interface{}) {
p.value(-1, reflect.ValueOf(in).Elem(), nil)
}
how to use
func main() {
var NamePtr string = "golang"
var SubNamePtr string = "*secure"
testUser := User{
ID: 1,
Name: "lumo",
NamePtr: &NamePtr,
SubStruct: []Tag{{
Name: "go",
},
},
SubStructPtr: []*Tag{&Tag{
Name: "*go",
NamePtr: &SubNamePtr,
},
},
}
var p = Patcher{
// filter - return true if the field in struct has a tag process=true
Matcher: func(structFiled *reflect.StructField, v reflect.Value) bool {
return HasTag(*structFiled, "process", "yes")
},
// process
Process: func(in string) string {
if in != "" {
return fmt.Sprintf("!%s!", strings.ToUpper(in))
} else {
return "!empty!"
}
return in
},
}
p.Apply(&testUser)
fmt.Println("Output:")
fmt.Println(Stringify(testUser))
}
goplay
https://goplay.tools/snippet/-0MHDfKr7ax
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
}
}
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.
The strings.Join function takes slices of strings only:
s := []string{"foo", "bar", "baz"}
fmt.Println(strings.Join(s, ", "))
But it would be nice to be able to pass arbitrary objects which implement a ToString() function.
type ToStringConverter interface {
ToString() string
}
Is there something like this in Go or do I have to decorate existing types like int with ToString methods and write a wrapper around strings.Join?
func Join(a []ToStringConverter, sep string) string
Attach a String() string method to any named type and enjoy any custom "ToString" functionality:
package main
import "fmt"
type bin int
func (b bin) String() string {
return fmt.Sprintf("%b", b)
}
func main() {
fmt.Println(bin(42))
}
Playground: http://play.golang.org/p/Azql7_pDAA
Output
101010
When you have own struct, you could have own convert-to-string function.
package main
import (
"fmt"
)
type Color struct {
Red int `json:"red"`
Green int `json:"green"`
Blue int `json:"blue"`
}
func (c Color) String() string {
return fmt.Sprintf("[%d, %d, %d]", c.Red, c.Green, c.Blue)
}
func main() {
c := Color{Red: 123, Green: 11, Blue: 34}
fmt.Println(c) //[123, 11, 34]
}
Another example with a struct :
package types
import "fmt"
type MyType struct {
Id int
Name string
}
func (t MyType) String() string {
return fmt.Sprintf(
"[%d : %s]",
t.Id,
t.Name)
}
Be careful when using it,
concatenation with '+' doesn't compile :
t := types.MyType{ 12, "Blabla" }
fmt.Println(t) // OK
fmt.Printf("t : %s \n", t) // OK
//fmt.Println("t : " + t) // Compiler error !!!
fmt.Println("t : " + t.String()) // OK if calling the function explicitly
This works well
package main
import "fmt"
type Person struct {
fname, sname string
address string
}
func (p *Person) String() string {
s:= fmt.Sprintf("\n %s %s lives at %s \n", p.fname, p.sname, p.address)
return s
}
func main(){
alex := &Person{"Alex", "Smith", "33 McArthur Bvd"}
fmt.Println(alex)
}
Output:
Alex Smith lives at 33 McArthur Bvd
If you have a fixed set of possible types for elements that could be converted, then you can define conversion functions for each, and a general conversion function that uses reflection to test the actual type of an element and call the relevant function for that element, eg:
func ToStringint(x int) string {
return strconv.Itoa(x)
}
func ToStringlong(x int64) string {
return strconv.FormatInt(x,10)
}
func ToStringdouble(x float64) string {
return fmt.Sprintf("%f", x)
}
func ToStringboolean(x bool) string {
if x {
return "true"
}
return "false"
}
func ToStringOclAny(x interface{}) string {
if reflect.TypeOf(x) == TYPEint {
return strconv.Itoa(x.(int))
}
if reflect.TypeOf(x) == TYPEdouble {
return fmt.Sprintf("%f", x.(float64))
}
if reflect.TypeOf(x) == TYPElong {
return strconv.FormatInt(x.(int64),10)
}
if reflect.TypeOf(x) == TYPEString {
return x.(string)
}
if reflect.TypeOf(x) == TYPEboolean {
return ToStringboolean(x.(bool))
}
if reflect.TypeOf(x) == TYPESequence {
return ToStringSequence(x.(*list.List))
}
if reflect.TypeOf(x) == TYPEMap {
return ToStringMap(x.(map[interface{}]interface{}))
}
return ""
}
func ToStringSequence(col *list.List) string {
res := "Sequence{"
for e := col.Front(); e != nil; e = e.Next() {
res = res + ToStringOclAny(e.Value)
if e.Next() != nil {
res = res + ", "
}
}
return res + "}"
}
func ToStringSet(col *list.List) string {
res := "Set{"
for e := col.Front(); e != nil; e = e.Next() {
res = res + ToStringOclAny(e.Value)
if e.Next() != nil {
res = res + ", "
}
}
return res + "}"
}
func ToStringMap(m map[interface{}]interface{}) string {
res := "Map{"
for i, v := range m {
res = res + ToStringOclAny(i) + " |-> " + ToStringOclAny(v) + " "
}
return res + "}"
}
Here is a simple way to handle this:
package main
import (
"fat"
"strconv"
)
type Person struct {
firstName, lastName string
age int
}
func (p Person) GetFullName() string {
return p.firstName + " " + p.lastName
}
func (p Person) GetAge() int {
return p.age
}
func (p Person) GetAgeAsString() string {
return strconv.Itoa(p.age)
}
func main() {
p := Person {"John", "Doe", 21}
fmt.Println(p.GetFullName())
fmt.Println(p.GetAgeAsString())
}
Output:
"John Doe"
"21"
I prefer something like the following:
type StringRef []byte
func (s StringRef) String() string {
return string(s[:])
}
…
// rather silly example, but ...
fmt.Printf("foo=%s\n",StringRef("bar"))