I'm trying to understand interfaces in Go. I wrote this:
package main
import "fmt"
type Animal struct {
Name string
Ability string
}
type AbilityShower interface {
ShowAbility() string
}
func (a Animal) ShowAbility() string {
return fmt.Sprintf("%s can %s", a.Name, a.Ability)
}
func main() {
var Dog Animal = Animal{
Name: "Dog",
Ability: "Walk",
}
Dog.ShowAbility()
}
But when I run with go run main.go nothing appears in the console. What am I doing incorrectly?
You are not printing the result. Change the main to
func main() {
var Dog Animal = Animal{
Name: "Dog",
Ability: "Walk",
}
fmt.Println(Dog.ShowAbility())
}
FYI: fmt.Sprintf() returns a string and doesn't print it to standard output
// Sprintf formats according to a format specifier and returns the
resulting string.
You are returning a string from the ShowAbility method, but not outputting it.
package main
import "fmt"
type Animal struct {
Name string
Ability string
}
type AbilityShower interface {
ShowAbility()
}
func (a Animal) ShowAbility() {
fmt.Printf("%s can %s", a.Name, a.Ability)
}
func main() {
var Dog Animal = Animal{
Name: "Dog",
Ability: "Walk",
}
Dog.ShowAbility()
}
Here you are using fmt.Sprintf which actually works like Scanf returning value. You need to assign that value to a variable and print the output.
func main() {
var Dog Animal = Animal{
Name: "Dog",
Ability: "Walk",
}
output := Dog.ShowAbility()
fmt.Println(output)
}
If you wants to print when calling the function ShowAbility() you can use Printf function of fmt package.
func (a Animal) ShowAbility() {
fmt.Printf("%s can %s", a.Name, a.Ability)
}
func main() {
var Dog Animal = Animal{
Name: "Dog",
Ability: "Walk",
}
Dog.ShowAbility()
}
Related
Here has an interface SpecificTemplate nested inside struct Template:
package main
import (
"encoding/json"
"fmt"
)
type SpecificTemplate interface {
GetLabel() string
}
type TemplateA struct {
Label string `json:"label"`
}
func (t TemplateA) GetLabel() string {
return t.Label
}
type Template struct {
Id int64 `json:"id"`
SpecificTemplate
}
func main() {
ta := TemplateA{
Label: `label1`,
}
t := Template{
Id: 1,
SpecificTemplate: ta,
}
data, _ := json.Marshal(t)
fmt.Println(string(data))
}
It would be
{
"id":1,
"SpecificTemplate":{
"label":"label1"
}
}
I wanna kown how to show json at same level, just like:
{
"id":1,
"label":"label1"
}
It kinda depends on the level of complexity you wanna reach...
If you want to expose only the label I should advice you to create a MarshalJSON function, just like this...
func (t Template) MarshalJSON() ([]byte, error) {
return json.Marshal(&struct {
Id int64 `json:"id"`
Label string `json:"label"`
}{
Id: t.Id,
Label: t.SpecificTemplate.GetLabel(),
})
}
With this your json.Marshal(t) will call this function and you will receive a flattened json...
However if you want to expose more Fields from the template you should use reflection, as pointed out by Iain Duncan in his comment
I have an issue encoding struct to json my code is
type MainStructure struct {
Text string json:"text,omitempty"
Array []TestArray json:"test_array,omitmepty"
}
type TestArray struct {
ArrayText string json:"array_text,omitempty"
}
func main() {
Test := MainStructure{
Text: "test",
Array: [
{
ArrayText: "test1"
},
{
ArrayText: "test2"
}
]
}
body := new(bytes.Buffer)
json.NewEncoder(body).Encode(&Test)
fmt.Println(string([]byte(body)))
}
the wanted result should be
{
"text": "test",
"test_array": [
{
"array_text": "test1"
},
{
"array_text": "test2"
}
]
}
I do not mind if it's "Marshal" or "encoding/json"
To encode a struct to JSON string, there are three ways that provided by standard library :
Using Encoder which convert struct to JSON string, then write it to io.Writer. This one usually used if you want to send JSON data as HTTP request, or saving the JSON string to a file.
Using Marshal which simply convert struct to bytes, which can be easily converted to string.
Using MarshalIndent which works like Marshal, except it's also prettify the output. This is what you want for your problem right now.
To compare between those three methods, you can use this code (Go Playground):
package main
import (
"bytes"
"encoding/json"
"fmt"
)
type MainStructure struct {
Text string `json:"text,omitempty"`
Array []TestArray `json:"test_array,omitempty"`
}
type TestArray struct {
ArrayText string `json:"array_text,omitempty"`
}
func main() {
Test := MainStructure{
Text: "test",
Array: []TestArray{
{ArrayText: "test1"},
{ArrayText: "test2"},
},
}
// Using marshal indent
btResult, _ := json.MarshalIndent(&Test, "", " ")
fmt.Println("Using Marshal Indent:\n" + string(btResult))
// Using marshal
btResult, _ = json.Marshal(&Test)
fmt.Println("\nUsing Marshal:\n" + string(btResult))
// Using encoder
var buffer bytes.Buffer
json.NewEncoder(&buffer).Encode(&Test)
fmt.Println("\nUsing Encoder:\n" + buffer.String())
}
The output will look like this :
Using Marshal Indent:
{
"text": "test",
"test_array": [
{
"array_text": "test1"
},
{
"array_text": "test2"
}
]
}
Using Marshal:
{"text":"test","test_array":[{"array_text":"test1"},{"array_text":"test2"}]}
Using Encoder:
{"text":"test","test_array":[{"array_text":"test1"},{"array_text":"test2"}]}
First of all I think you are going wrong on how to create a struct in go, as you can easily convert them to json.
You should be first making a proper struct then do json.marshal(Test) to convert it to proper json like:
package main
import (
"encoding/json"
"fmt"
)
func main() {
type TestArray struct {
ArrayText string `json:"array_text,omitempty"`
}
type MainStructure struct {
Text string `json:"text,omitempty"`
Array []TestArray `json:"test_array,omitmepty"`
}
Test := MainStructure{
Text: "test",
Array: []TestArray{
TestArray{ArrayText: "test1"},
TestArray{ArrayText: "test2"},
}}
bytes, err := json.Marshal(Test)
if err != nil {
fmt.Println("eror marshalling")
} else {
fmt.Println(string(bytes))
}
}
Check this out on play.golang.org
I could not get the point you wanted to use bytes.Buffer if your objective is just to put the result into the console. Assuming the point is:
Create a struct instance (corresponding to a JSON object)
Emit it in the screen
The following code can help you:
package main
import "encoding/json"
import "fmt"
type MainStructure struct {
Text string `json:"text,omitempty"`
Array []TestArray `json:"test_array,omitmepty"`
}
type TestArray struct {
ArrayText string `json:"array_text,omitempty"`
}
func main() {
Test := MainStructure{
Text: "test",
Array: []TestArray{
TestArray{"test1"},
TestArray{"test2"},
},
}
res, _ := json.MarshalIndent(Test, "", "\t")
fmt.Println(string(res))
}
json.MarshalIndent is used to make result pretty-formatted, if you bother it.
I have a JSON which contain some static and dynamic data. Below is a sample of JSON
{
"request": { /*Static data start */
"data": {
"object": { /*Static data ends here*/
"user": { /*Dynamic data start here */
"userid": "andmmdn",
"ipaddr": "1.1.1.1",
"noofusers": "100",
"qos": "34",
"id": "kldjflkdfjlkdjfkld",
"domain": "xyz.com" /*Dynamic data ends here */
}
}
}
}
}
Below is the code which can create this JSON
package main
import (
"fmt"
"encoding/json"
)
//ReqJSON struct
type ReqJSON struct {
Request Request `json:"request"`
}
//Request struct
type Request struct {
Data Data `json:"data"`
}
//Data struct
type Data struct {
Object Object `json:"object"`
}
//Object struct
type Object struct {
User User `json:"user"`
}
//User struct
type User struct {
UserID string `json:"userid"`
IPAddr string `json:"ipaddr"`
Noofusers string `json:"noofusers"`
Qos string `json:"qos"`
ID string `json:"id"`
Domain string `json:"domain"`
}
func main() {
test := ReqJSON {
Request{
Data: Data{
Object: Object{
User: User{
UserID: "andmmdn",
IPAddr: "1.1.1.1",
Noofusers: "100",
Qos: "34",
ID: "kldjflkdfjlkdjfkld",
Domain: "xyz.com",
},
},
},
},
}
jsonEncode, _ := json.Marshal(test)
jsonIdent, _ := json.MarshalIndent(&test, "", "\t")
fmt.Println(string(jsonEncode))
fmt.Println(string(jsonIdent))
}
As you can see from above it contain struct which doesn't make much sense as they act more like placeholder for nesting the data. So how we make it more optimized. As all the data is being taken care in the last struct. What approach for unmarshaling of the data should be applied as the response will be in same format and want to use the last struct for the same.
Any thoughts on the approach.
Also how to make a generic struct as I multiple API which uses same struct below is an example
//ReqJSON for populating data
type ReqJSON struct {
Request struct {
Data struct {
Object struct {
Auth Auth `json:"auth"`
} `json:"object"`
} `json:"data"`
} `json:"request"`
}
//ReqJSON for populating data
type ReqJSON struct {
Request struct {
Data struct {
Object struct {
Error Error `json:"error"`
} `json:"object"`
} `json:"data"`
} `json:"request"`
}
If you don't need the wrapping types for anything besides marshaling/unmarshaling, you can define them anonymously:
type ReqJSON struct {
Request struct {
Data struct {
Object struct {
User User `json:"user"`
} `json:"object"`
} `json:"data"`
} `json:"request"`
}
type User struct {
UserID string `json:"userid"`
IPAddr string `json:"ipaddr"`
Noofusers string `json:"noofusers"`
Qos string `json:"qos"`
ID string `json:"id"`
Domain string `json:"domain"`
}
And, borowing from icza's answer, you can add accessor methods to ReqJSON:
func (j *ReqJSON) User() User { return j.Request.Data.Object.User }
func (j *ReqJSON) SetUser(u User) { j.Request.Data.Object.User = u }
func main() {
var j ReqJSON
j.SetUser(User{
UserID: "_id",
IPAddr: "1.1.1.1",
Noofusers: "100",
Qos: "34",
ID: "kldjflkdfjlkdjfkld",
Domain: "xyz.com",
})
b, err := json.MarshalIndent(j, "", " ")
fmt.Println(err, string(b))
}
That sounds about right. The solution is a little verbose / redundant, but so is the data format you have to deal with.
To work with that easily, you may create helper functions and use them:
func wrap(u User) *ReqJSON {
return &ReqJSON{Request: Request{Data: Data{Object: Object{User: u}}}}
}
func unwrap(r *ReqJSON) User {
return r.Request.Data.Object.User
}
But other than that, you can't really simplify other things.
So marshaling a User is like:
var u User
data, err := json.Marshal(wrap(u))
Unmarshaling is:
var r *ReqJSON
err := json.Unmarshal(data, &r)
// Check error
u := unwrap(r) // Here we have the user
You can't eliminate the complexity, but you could potentially hide some of it inside of a custom Marshaler:
type Request struct {
UserID string `json:"userid"`
IPAddr string `json:"ipaddr"`
Noofusers string `json:"noofusers"`
Qos string `json:"qos"`
ID string `json:"id"`
Domain string `json:"domain"`
}
func (r *Request) MarshalJSON() ([]byte, error) {
type request struct {
Data struct {
Object struct {
User struct {
Request
} `json:"user"`
} `json:"object"`
} `json:"data"`
}
structure := request{Data: data{Object: object{User: user{r}}}}
return json.Marshal(structure)
}
The same approach can be employed in reverse for UnmarshalJSON, if desired.
I have a struct like so:
type my_struct struct {
First string `json:"first"`
Second string `json:"second"`
Number int `json:"number"`
}
When I marshal that into JSON, it outputs very simple JSON as you'd expect:
var output_json []byte
output_json, _ = json.Marshal(output)
fmt.Println(string(output_json))
Result:
{"first":"my_string","second":"another_string","number":2}
All fine so far!
What I'd like to do, before marshalling that struct into JSON, is nest it inside another struct. The resulting output would be JSON that looks like this:
{
"fields": {
"first": "my_string",
"number": 2,
"second": "another_string"
},
"meta": "data"
}
How can I do that?
I think you could statically declare another struct to use:
type WrappedOutput struct {
fields my_struct
meta string
}
Then you could embed your struct before marshalling
o := WrappedOutput{fields: output}
Brand new to go so not sure if this is the easiest way to do it
The clean way to do this would be to declare 2 structs (I've done it globally below) and nest My_struct inside the higher level struct.
Then you can initialize the higher level struct before Mashalling it:
package main
import (
"encoding/json"
"fmt"
)
type My_struct struct {
First string `json:"first"`
Second string `json:"second"`
Number int `json:"number"`
}
type Big_struct struct {
Fields My_struct
Meta string
}
func main() {
output := Big_struct{
Fields: My_struct{
First: "my_string",
Second: "another_string",
Number: 2,
},
Meta: "data",
}
output_json, err := json.Marshal(output)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(output_json))
}
if you don't want Big_struct you can declare an anonymous struct within your code as you need it and nest My_struct inside:
package main
import (
"encoding/json"
"fmt"
)
type My_struct struct {
First string `json:"first"`
Second string `json: "second"`
Number int `json:"number"`
}
func main() {
output := struct {
Fields My_struct
Meta string
}{
Fields: My_struct{
First: "my_string",
Second: "another_string",
Number: 2,
},
Meta: "data",
}
output_json, err := json.Marshal(output)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(output_json))
}
If you don't want to use a new structure, you can do:
data := my_struct{First: "first", Second: "2", Number: 123}
result, _ := json.Marshal(&map[string]interface{}{"fields":data,"meta":"data"})
fmt.Println(string(result))
it's not clean, but it does the work.
In Java I can do something like
derp(new Runnable { public void run () { /* run this sometime later */ } })
and "run" the code in the method later. It's a pain to handle (anonymous inner class), but it can be done.
Does Go have something that can facilitate a function/callback being passed in as a parameter?
Yes, consider some of these examples:
package main
import "fmt"
// convert types take an int and return a string value.
type convert func(int) string
// value implements convert, returning x as string.
func value(x int) string {
return fmt.Sprintf("%v", x)
}
// quote123 passes 123 to convert func and returns quoted string.
func quote123(fn convert) string {
return fmt.Sprintf("%q", fn(123))
}
func main() {
var result string
result = value(123)
fmt.Println(result)
// Output: 123
result = quote123(value)
fmt.Println(result)
// Output: "123"
result = quote123(func(x int) string { return fmt.Sprintf("%b", x) })
fmt.Println(result)
// Output: "1111011"
foo := func(x int) string { return "foo" }
result = quote123(foo)
fmt.Println(result)
// Output: "foo"
_ = convert(foo) // confirm foo satisfies convert at runtime
// fails due to argument type
// _ = convert(func(x float64) string { return "" })
}
Play: http://play.golang.org/p/XNMtrDUDS0
Tour: https://tour.golang.org/moretypes/25 (Function Closures)
You can pass function as parameter to a Go function. Here is an example of passing function as parameter to another Go function:
package main
import "fmt"
type fn func(int)
func myfn1(i int) {
fmt.Printf("\ni is %v", i)
}
func myfn2(i int) {
fmt.Printf("\ni is %v", i)
}
func test(f fn, val int) {
f(val)
}
func main() {
test(myfn1, 123)
test(myfn2, 321)
}
You can try this out at: https://play.golang.org/p/9mAOUWGp0k
Here is the sample "Map" implementation in Go. Hope this helps!!
func square(num int) int {
return num * num
}
func mapper(f func(int) int, alist []int) []int {
var a = make([]int, len(alist), len(alist))
for index, val := range alist {
a[index] = f(val)
}
return a
}
func main() {
alist := []int{4, 5, 6, 7}
result := mapper(square, alist)
fmt.Println(result)
}
Here is a simple example:
package main
import "fmt"
func plusTwo() (func(v int) (int)) {
return func(v int) (int) {
return v+2
}
}
func plusX(x int) (func(v int) (int)) {
return func(v int) (int) {
return v+x
}
}
func main() {
p := plusTwo()
fmt.Printf("3+2: %d\n", p(3))
px := plusX(3)
fmt.Printf("3+3: %d\n", px(3))
}
This is the simplest way I can come with.
package main
import "fmt"
func main() {
g := greeting
getFunc(g)
}
func getFunc(f func()) {
f()
}
func greeting() {
fmt.Println("Hello")
}
I hope the below example will provide more clarity.
package main
type EmployeeManager struct{
category string
city string
calculateSalary func() int64
}
func NewEmployeeManager() (*EmployeeManager,error){
return &EmployeeManager{
category : "MANAGEMENT",
city : "NY",
calculateSalary: func() int64 {
var calculatedSalary int64
// some formula
return calculatedSalary
},
},nil
}
func (self *EmployeeManager) emWithSalaryCalculation(){
self.calculateSalary = func() int64 {
var calculatedSalary int64
// some new formula
return calculatedSalary
}
}
func updateEmployeeInfo(em EmployeeManager){
// Some code
}
func processEmployee(){
updateEmployeeInfo(struct {
category string
city string
calculateSalary func() int64
}{category: "", city: "", calculateSalary: func() int64 {
var calculatedSalary int64
// some new formula
return calculatedSalary
}})
}
You can also pass the function of a struct, like:
package main
// define struct
type Apple struct {}
// return apple's color
func (Apple) GetColor() string {
return "Red"
}
func main () {
// instantiate
myApple := Apple{}
// put the func in a variable
theFunc := myApple.GetColor
// execute the variable as a function
color := theFunc()
print(color)
}
output will be "Red", check on the playground
Yes Go does accept first-class functions.
See the article "First Class Functions in Go" for useful links.