ToString() function in Go - go

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"))

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?

golang patch string values on an object, recursive with filtering

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

How to update slice inside map

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}

common function to create map[string]struct from slice of struct dynamically

I have two different struct as mentioned below A abd B and two process functions. Is there any way by means of which i can write a common function to generate the map[string]struct for the both the struct. Moreover, is there any way using reflection given the struct name i can create the object of the same?
type A struct {
name string
// more fields
}
type B struct {
name string
// more fields
}
func ProcessA(input []A) map[string]A {
output := make(map[string]A)
for _, v := range input {
output[v.name] = v
}
return output
}
func ProcessB(input []B) map[string]B {
output := make(map[string]B)
for _, v := range input {
output[v.name] = v
}
return output
}
Idiomatic way in Go would be to use interface.
type Named interface {
Name() string
}
type letter struct {
name string
}
func (l letter) Name() string {
return l.name
}
type A struct {
letter
// more fields
}
type B struct {
letter
// more fields
}
func ProcessNameds(input []Named) map[string]Named {
output := make(map[string]Named, len(input))
for _, v := range input {
output[v.Name()] = v
}
return output
}
Well, see if something like this would help:
package main
import (
"fmt"
"strconv"
)
type A struct {
name string
// more fields
}
type B struct {
name string
// more fields
}
func Process(x interface{}) interface{} {
ma := make(map[string]int)
mb := make(map[string]string)
if x == nil {
return nil
} else if a, ok := x.([]A); ok {
fmt.Printf("Type A argument passed %s\n", x)
ma[a[0].name] = 1
ma[a[1].name] = 2
return ma //you can return whatever type you want here
} else if b, ok := x.([]B); ok {
fmt.Printf("Type B argument passed %s\n", x)
mb[b[0].name] = "a"
mb[b[1].name] = "b"
return mb //you can return whatever type you want here
} else {
panic(fmt.Sprintf("Unexpected type %T: %v", x, x))
}
return nil
}
func main() {
a := make([]A, 5)
for i := 0; i < len(a); i++ {
a[i].name = strconv.Itoa(i) + "A"
}
b := make([]B, 7)
for i := 0; i < len(b); i++ {
b[i].name = strconv.Itoa(i) + "B"
}
fmt.Println(Process(a))
fmt.Println(Process(b))
//Uncomment line below to see the panic
//fmt.Println(Process(8))
}
https://play.golang.org/p/irdCsbpvUv_t

How do you create a slice of functions with different signatures?

How do you create a slice of functions with different signatures? I tried the code below but its feels hack-ish. Do we just bite the bullet and use a slice interface{}?
package main
import (
"fmt"
)
type OneParams func(string) string
type TwoParams func(string, string) string
type ThreeParams func(string, string, string) string
func (o OneParams) Union() string {
return "Single string"
}
func (t TwoParams) Union() string {
return "Double string"
}
func (t ThreeParams) Union() string {
return "Triple string"
}
type Functions interface {
Union() string
}
func Single(str string) string {
return str
}
func Double(str1 string, str2 string) string {
return str1 + " " + str2
}
func Triple(str1 string, str2 string, str3 string) string {
return str1 + " " + str2 + " " + str3
}
func main() {
fmt.Println("Slice Of Functions Program!\n\n")
fSlice := []Functions{
OneParams(Single),
TwoParams(Double),
ThreeParams(Triple),
}
for _, value := range fSlice {
switch t := value.(type) {
case OneParams:
fmt.Printf("One: %s\n", t("one"))
case TwoParams:
fmt.Printf("Two: %s\n", t("one", "two"))
case ThreeParams:
fmt.Printf("Three: %s\n", t("one", "two", "three"))
default:
fmt.Println("Huh! What's that?")
}
}
fmt.Println("\n\n")
}
Is this just a case of trying to do too much with Go?
Please check it, I don't know if it what you want. Because I don't know what are you exactly want.
package main
import (
"fmt"
"reflect"
)
func A() {
fmt.Println("A")
}
func B(A int) {
fmt.Println("B", A)
}
func C(A string, B float32) {
fmt.Println("C", A, B)
}
func main() {
f := []interface{}{A, B, C}
f[0].(func())()
f[1].(func(int))(15)
f[2].(func(string, float32))("TEST", 90)
fmt.Println("\n******* another thing ******")
for a, v := range f {
v := reflect.TypeOf(v)
fmt.Println("#######", a)
fmt.Println("num param :", v.NumIn())
for i := 0; i < v.NumIn(); i++ {
fmt.Println("param :", i, "type is ", v.In(i))
}
}
}
Check on Go Playground
Here I have another example calling using reflect
package main
import (
"fmt"
"reflect"
)
func A() {
fmt.Println("A")
}
func B(A int) {
fmt.Println("B", A)
}
func C(A string, B float32) {
fmt.Println("C", A, B)
}
func main() {
f := []interface{}{A, B, C}
f[0].(func())()
f[1].(func(int))(15)
f[2].(func(string, float32))("TEST", 90)
fmt.Println("\n******* calling with reflect ******")
for a, v := range f {
v := reflect.TypeOf(v)
//calling the function from reflect
val := reflect.ValueOf(f[a])
params := make([]reflect.Value, v.NumIn())
if v.NumIn() == 1 {
params[0] = reflect.ValueOf(1564)
} else if v.NumIn() == 2 {
params[0] = reflect.ValueOf("Test FROM reflect")
params[1] = reflect.ValueOf(float32(123456))
}
val.Call(params)
}
}
Check on Go Playground
depends on what the different you need. upon your example, we could use variadic.
package main
import(
"fmt"
"strings"
)
func foo(ss ...string) string{
return strings.Join(ss, " ")
}
func main(){
fmt.Println(foo("one"))
fmt.Println(foo("one", "two"))
fmt.Println(foo("one", "two", "three"))
}

Resources