Type conversion . Unable to convert to string in golang [duplicate] - go

In this bizarre example, someone has created a new type which is really just a string:
type CustomType string
const (
Foobar CustomType = "somestring"
)
func SomeFunction() string {
return Foobar
}
However, this code fails to compile:
cannot use Foobar (type CustomType) as type string in return argument
How would you fix SomeFunction so that it is able to return the string value of Foobar ("somestring") ?

Convert the value to a string:
func SomeFunction() string {
return string(Foobar)
}

Better to define a String function for the Customtype - it can make your life easier over time - you have better control over things as and if the structure evolves. If you really need SomeFunction then let it return Foobar.String()
package main
import (
"fmt"
)
type CustomType string
const (
Foobar CustomType = "somestring"
)
func main() {
fmt.Println("Hello, playground", Foobar)
fmt.Printf("%s", Foobar)
fmt.Println("\n\n")
fmt.Println(SomeFunction())
}
func (c CustomType) String() string {
fmt.Println("Executing String() for CustomType!")
return string(c)
}
func SomeFunction() string {
return Foobar.String()
}
https://play.golang.org/p/jMKMcQjQj3

For every type T, there is a corresponding conversion operation T(x)
that converts the value x to type T. A conversion from one type to
another is allowed if both have the same underlying type, or if both
are unnamed pointer types that point to variables of the same
underlying type; these conversions change the type but not the
representation of the value. If x is assignable to T, a conversion
is permitted but is usually redundant. - Taken from The Go
Programming Language - by Alan A. A. Donovan
As per your example here are some of the different examples which will return the value.
package main
import "fmt"
type CustomType string
const (
Foobar CustomType = "somestring"
)
func SomeFunction() CustomType {
return Foobar
}
func SomeOtherFunction() string {
return string(Foobar)
}
func SomeOtherFunction2() CustomType {
return CustomType("somestring") // Here value is a static string.
}
func main() {
fmt.Println(SomeFunction())
fmt.Println(SomeOtherFunction())
fmt.Println(SomeOtherFunction2())
}
It will output:
somestring
somestring
somestring
The Go Playground link

You can convert like this:
var i int = 42
var f float64 = float64(i)
check here
you can return like this:
return string(Foobar)

Related

Dereference function interface argument when argument is a pointer

When my function is given an interface argument that is a pointer I would like to update the pointer to something else (a* = b*). If the function argument is not an interface and is instead a pointer, this works fine.
Given the following code:
package main
import "fmt"
type demoInterface interface {
GetName() string
}
type demoStruct struct {
name string
}
func (d demoStruct ) GetName() string {
return d.name
}
func Update(d1 demoInterface) {
fmt.Println(d1)
d2 := demoStruct{name: "bob"}
d1 = &d2
fmt.Println(d1)
}
func main() {
d1 := &demoStruct{name: "frank"}
fmt.Println(d1)
Update(d1)
fmt.Println(d1)
}
The output is
&{frank}
&{frank}
&{bob}
&{frank}
However I would actually expect
&{frank}
&{frank}
&{bob}
&{bob}
If I replace the Update function signature to accept a *demoStruct instead of a demoInterface it works as expected.
Is there a way to get this to work as expected when the functions signature is an interface rather than a pointer.
Thanks.
If you really need this, it could be one of the rare cases where a pointer to an interface may make sense. Here's your example modified with that:
package main
import "fmt"
type demoInterface interface {
GetName() string
}
type demoStruct struct {
name string
}
func (d demoStruct ) GetName() string {
return d.name
}
func Update(d1 *demoInterface) {
fmt.Println(*d1)
d2 := demoStruct{name: "bob"}
*d1 = d2
fmt.Println(*d1)
}
func main() {
d1 := demoInterface(demoStruct{name: "frank"})
fmt.Println(d1)
Update(&d1)
fmt.Println(d1)
}
Note that since Update takes *demoInterface, we can't just pass in *demoStruct (Go has no type covariance), so we have to convert the struct to the interface first.

Why my Golang defined method not implemented implicitily while String() does

In https://tour.golang.org/methods/11
It states Under the hood, interface values can be thought of as a tuple of a value and a concrete type
I define M as follows
script1
package main
import (
"fmt"
)
type I interface {
M() string
}
type T struct {
S string
w string
}
func (t T) M() string {
return "dddd"
}
func main() {
var i I
i = T{"Hello","eeee"}
fmt.Printf("(%v, %T)", i, i)
fmt.Println(i)
}
This prints out ({Hello eee}, main.T){Hello eee}
interface i has vaule {Hello eee} and type main.T
script2:
package main
import (
"fmt"
)
type I interface {
M() string
}
type T struct {
S string
w string
}
func (t T) M() string {
return "dddd"
}
func (t T) String() string {
return "ccccc"
}
func main() {
var i I
i = T{"Hello","eeee"}
fmt.Printf("(%v, %T)", i, i)
fmt.Println(i)
}
This prints out (ccccc, main.T)ccccc.
interface i has vaule ccccc and type main.T
Seems when i add String() as Stringer defined by the fmt package in script2. The String() is implemented implicitily,not sure why?
I thought in script2 i would have value "{Hello eee}" and type main.T
You should call fmt.Println(i.M()) ?
Why you want fmt call a function while its'n exist?
A Stringer is a type that can describe itself as a string. The fmt package (and many others) look for this interface to print values
Refer: https://golang.org/pkg/fmt/#Stringer
Stringer is implemented by any value that has a String method, which
defines the “native” format for that value. The String method is used
to print values passed as an operand to any format that accepts a
string or to an unformatted printer such as Print.
In your case, in script1 you are just printing out the struct. In script2 you are providing what the builder should use when an unformatted print occurs which is a function that prints out "ccccc".

How to disallow direct struct initialization

Given the following packages in Go, is it possible to prevent the direct initialization of Bar with Bar{..} without de-exposing Bar from the package?
package bar:
package bar
import ()
type Bar struct {
A string
B string
}
func NewBar(baz string) Bar{
return Bar{A:baz, B:baz+baz}
}
package main:
package main
import (
"fmt"
"./bar"
)
func main() {
x := bar.NewBar("sad") //all bars should be created with this
y := bar.Bar{A: "fadss"} //and this should be disallowed
bzzBar(x)
bzzBar(y)
}
func bzzBar(bzz bar.Bar) { //but I can't do 'Bar -> bar' because I want to use the type
fmt.Println(bzz)
}
My gut feeling says this can't be done, so that is also a valid answer.
There is no way to prevent Bar{} or Bar{A: "foo"}.
To control a struct the way you want you can return an interface instead and not export the struct itself.
Example given:
package bar
type Bar interface{
A() string
B() string
// if you need setters
SetA(string)
SetB(string)
}
type bar struct {
a string
b string
}
func (b *bar) A() string { return b.a }
func (b *bar) B() string { return b.b }
func (b *bar) SetA(val string) { b.a = val }
func (b *bar) SetB(val string) { b.b = val }
func NewBar(baz string) Bar {
return &bar{a:baz, b:baz+baz}
}
The idiom used in the Go standard library is:
package bar
package bar
import (
"fmt"
)
type Bar struct {
a string
b string
}
func New(baz string) *Bar {
return &Bar{a: baz, b: baz + baz}
}
func (b *Bar) BzzBar() {
fmt.Println(*b)
}
package main
package main
import (
"bar"
)
func main() {
x := bar.New("sad") //all bars should be created with this
x.BzzBar()
// error: unknown bar.Bar field 'A' in struct literal
// y := bar.Bar{A: "fadss"} //and this should be disallowed
}
Output:
{sad sadsad}
ADDENDUM:
The Go Programming Language Specification
The zero value
When memory is allocated to store a value, either through a
declaration or a call of make or new, and no explicit initialization
is provided, the memory is given a default initialization. Each
element of such a value is set to the zero value for its type: false
for booleans, 0 for integers, 0.0 for floats, "" for strings, and nil
for pointers, functions, interfaces, slices, channels, and maps. This
initialization is done recursively, so for instance each element of an
array of structs will have its fields zeroed if no value is specified.
Another idiom used in the Go standard library is to make zero values meaningful. For example, if new has not been explicitly initialized it will have the zero value default of false.
type Bar struct {
new bool
a string
b string
}
For example,
package bar
import (
"fmt"
)
type Bar struct {
new bool
a string
b string
}
func New(baz string) *Bar {
return &Bar{new: true, a: baz, b: baz + baz}
}
func (b *Bar) notnew() {
if b == nil || !b.new {
panic("bar.Bar not bar.New")
}
}
func (b *Bar) Bzz() {
b.notnew()
fmt.Println(*b)
}
.
package main
import (
"bar"
)
func main() {
x := bar.New("sad") //all bars should be created with this
x.Bzz()
// error: unknown bar.Bar field 'A' in struct literal
// y := bar.Bar{A: "fadss"} //and this should be disallowed
// var b bar.Bar
// panic: bar.Bar not bar.New
// b.Bzz()
// var b = bar.Bar{}
// panic: bar.Bar not bar.New
// b.Bzz()
// var bp *bar.Bar
// panic: bar.Bar not bar.New
// bp.Bzz()
// var bp = new(bar.Bar)
// panic: bar.Bar not bar.New
// bp.Bzz()
}
Output:
{true sad sadsad}
You can make all Bar fields unexported and provide getters and setters for them. This way package users will still be able to do silly things like
a := Bar{}
b := Bar{"foo"}
neither or which seems useful (although the former can be used to create an empty Bar similar to &bytes.Buffer{}).
You should be able to not export A and B, if you provide a String() function:
type Bar struct {
a string
b string
}
func NewBar(baz string) Bar{
return Bar{a:baz, b:baz+baz}
}
func (Bar) String() string {
return a + " " b
}

How I can get return value based on argument type?

When I define function
func test(a int, b int) int {
//bla
}
I must set arguments and return value types. How I can return value based on argument type, ex
func test(argument type) type {
//if argument type == string, must return string
//or else if argument int, must return integer
}
Can I do this and how?
Go lacks generics, (not going to argue this point one way or the other), you can achieve this by passing interface{} to functions and then doing a type assertion on the other side.
package main
import "fmt"
func test(t interface{}) interface{} {
switch t.(type) {
case string:
return "test"
case int:
return 54
}
return ""
}
func main() {
fmt.Printf("%#v\n", test(55))
fmt.Printf("%#v", test("test"))
}
You will have to type assert the value you get out
v := test(55).(int)
Go does not yet have generics like C# or Java.
It does have an empty interface (interface{})
Here is code that I believe answers your question, if I understood it correctly:
package main
import (
"fmt"
"reflect"
)
type generic interface{} // you don't have to call the type generic, you can call it X
func main() {
n := test(10) // I happen to pass an int
fmt.Println(n)
}
func test(arg generic) generic {
// do something with arg
result := arg.(int) * 2
// check that the result is the same data type as arg
if reflect.TypeOf(arg) != reflect.TypeOf(result) {
panic("type mismatch")
}
return result;
}

Object Factory in golang

I am a new to golang. I need to design a function to create object of differing types based on input. But I failed to figure out how to design the interface. Here comes my code:
package main
import (
"fmt"
)
type AA struct{
name string
}
func (this *AA) say(){
fmt.Println("==========>AA")
}
type BB struct{
*AA
age int
}
func (this *BB) say(){
fmt.Println("==========>BB")
}
func ObjectFactory(type int) *AA {
if type ==1 {
return new(AA)
}else{
return new(BB)
}
}
func main() {
obj1 := ObjectFactory(0)
obj1.say()
obj2 := ObjectFactory(0)
obj2.say()
}
The compiler tells me error no matter I ask ObjectFactory return *AA or interface{}. How can I make it work?
First off, using type as a variable name is disallowed in go (see the spec). That is your first problem.
The return type of object factory is *AA. This means that it can only return variables of type *AA, which causes the return of type of BB to fail. As defined in the spec, go doesn't have type inheritance, just struct embedding.
If you create an interface called sayer, you can use that instead of *AA in your ObjectFactory function.
type sayer interface {
say()
}
You probably want to use this interface when trying to get multiple dispatch (as demonstrated in the code below (see on play.golang.org as well).
Try this code:
package main
import (
"fmt"
)
type sayer interface {
say()
}
type AA struct{
name string
}
func (this *AA) say(){
fmt.Println("==========>AA")
}
type BB struct{
*AA
age int
}
func (this *BB) say(){
fmt.Println("==========>BB")
}
func ObjectFactory(typeNum int) sayer {
if typeNum ==1 {
return new(AA)
}else{
return new(BB)
}
}
func main() {
obj1 := ObjectFactory(1)
obj1.say()
obj2 := ObjectFactory(0)
obj2.say()
}

Resources