简体   繁体   English

ToString() Go 中的 function

[英]ToString() function in Go

The strings.Join function takes slices of strings only: strings.Join function 仅采用字符串切片:

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.但是能够传递实现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 ? Go 中是否有类似的东西,或者我必须用 ToString 方法装饰现有类型,如int并在strings.Join周围编写一个包装器?

func Join(a []ToStringConverter, sep string) string

Attach a String() string method to any named type and enjoy any custom "ToString" functionality:String() string方法附加到任何命名类型并享受任何自定义“ToString”功能:

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游乐场: http ://play.golang.org/p/Azql7_pDAA


Output输出

101010

When you have own struct , you could have own convert-to-string function.当您拥有自己的struct时,您可以拥有自己的转换为字符串的功能。

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 :另一个带有 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亚历克斯·史密斯住在麦克阿瑟大道 33 号

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:如果对于可以转换的元素有一组固定的可能类型,那么您可以为每个定义转换函数,以及使用反射来测试元素的实际类型并为该元素调用相关 function 的通用转换 function,例如:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM