I am studying GO by using "a tour of go"
The code is doing very simple things, combine first and last together and output on screen.
The output is a hex address instead of "aaabbb" after I run the code. Could anyone can help me out? Thank you
package main
import "fmt"
type Name struct{
first,last string
}
func (name Name) fullName() string{
return (name.first + name.last)
}
func main(){
v := Name{"aaa","bbb"}
fmt.Println(v.fullName)
}
You are not calling the function fullName. you are just passing 'the pointer' to it:
see this http://play.golang.org/p/GjibbfoyH0
package main
import "fmt"
type Name struct {
first, last string
}
func (name Name) fullName() string {
return (name.first + name.last)
}
func main() {
v := Name{"aaa", "bbb"}
fmt.Println(v.fullName())
}
Use the result of the method
fmt.Println(v.fullName())
not the address of the method
fmt.Println(v.fullName)
For example,
package main
import "fmt"
type Name struct{
first,last string
}
func (name Name) fullName() string{
return (name.first + name.last)
}
func main(){
v := Name{"aaa","bbb"}
fmt.Println(v.fullName())
}
Output:
aaabbb
Related
I would like to know if it is possible to get the name of a property from a structure and convert it to string.
For example in the following code:
package main
import "fmt"
type StructA struct {
ValueAA string
ValueAB string
}
type StructB struct {
ValueBA string
ValueBB string
RefStructA StructA
}
func main() {
//pass any attribute of any structure
fmt.Println(castProperty(StructB.RefStructA.ValueAA))
//print the name passed but in string. Do not print the value
//expected output: "StructB.RefStructA.ValueAA"
}
func castProperty(value interface{}) string {
//some code
}
Is it possible to write a function that allows obtaining the name of the property of a structure and converted to a string? property value is not required.
That's called Reflection. I let you read the page, it lets you do what you want.
First, read the The first law of reflection: https://go.dev/blog/laws-of-reflection
package main
import (
"fmt"
"reflect"
)
func main() {
var x float64 = 3.4
fmt.Println("type:", reflect.TypeOf(x))
}
https://play.golang.org/p/OuGgD1TlSMO
I am not sure exactly how do you want to give input to your function but here is an example that may help you
package main
import (
"log"
"reflect"
)
func main() {
getPropertyName(B{})
}
type A struct {
field1 string
}
type B struct {
field A
}
func getPropertyName(b interface{}) {
parentType := reflect.TypeOf(b)
val := reflect.ValueOf(b)
for i := 0; i< val.Type().NumField(); i++ {
t := val.Type().Field(i)
ty := val.Type().Field(i).Type.Name()
log.Println(parentType.Name()+"."+ t.Name+"."+ty)
}
}
you could do something like this :
package main
import (
"fmt"
)
type StructA struct {
ValueAA string
ValueAB string
}
type StructB struct {
ValueBA string
ValueBB string
RefStructA StructA
}
func main() {
x := &StructB{RefStructA: StructA{ValueAA: "something"}}
fmt.Printf("%+v", x)
}
out :
&{ValueBA: ValueBB: RefStructA:{ValueAA:something ValueAB:}}
Problem at reflection, with MethodByName
Code:
package main
import (
"reflect"
"fmt"
)
type test struct {}
var serviceType = map[string]reflect.Value{
"test": reflect.ValueOf(test{}),
}
func (t *test) prnt() {
fmt.Println("test ok")
}
func callFunc(strct string, fName string) {
s := serviceType[strct].MethodByName(fName)
if !s.IsValid(){
fmt.Println("not correct")
return
}
s.Call(make([]reflect.Value,0))
}
func main() {
callFunc("test", "prnt")
}
Output:
not correct
Playground:
https://play.golang.org/p/ZLEQBGYoUOB
Could you help, what I'm doing wrong ?
Two things needs to be corrected.
MethodByName() returns only Exported methods. So you have to rename prnt tp Prnt
Needs to pass a pointer of struct test to reflect.ValueOf() method.
Here is the modified working code https://play.golang.org/p/4MK2kqOz6e2
package main
import (
"fmt"
)
type animal interface {
speak()
}
type dog struct {
name, sound string
}
type cat struct {
name, sound string
}
func (d dog) speak() {
fmt.Println(d.name, " goes ", d.sound)
}
func (c cat) speak() {
fmt.Println(c.name, " goes ", c.sound)
}
func animal_speak(a animal) {
fmt.Println(a.speak())
}
func main() {
dogo := dog{"scooby", "woof"}
cato := cat{"garfield", "meow"}
animal_speak(dogo)
animal_speak(cato)
}
When I call the animal interface it gives me the following error
./interface.go:28:21: a.speak() used as value
What am I doing wrong?
Link to playground
The interface is not used as a value. You're using a function call that returns nothing as a value.
speak() returns nothing... so what do you expect it to print?
Since you are printing the output of speak method, your speak method needs to return a string or an object whose string representation would print a string you would like to see. Here's your program modified https://play.golang.org/p/VDsp0cjXBd- to return a string.
This answer is based on all above answers,
Modified below function
Before
func animal_speak(a animal) {
fmt.Println(a.speak())
}
After
func animal_speak(a animal) {
a.speak()
}
Playgorund Link
This question already has answers here:
Using a setter for a struct type does not work as anticipated
(2 answers)
Closed 5 years ago.
I am making this code trying to understand the MVC architecture while learning Go, and I am stuck trying to change values in the model from the controller.
The code right now creates a model that only holds a string, the view shows that string on the terminal, but the controller can not change it (it gets the user input without any problem).
Right now the text I get in the terminal is like this:
Hello World!
asdf //my input
Hello World!
And the output I would like to get would be like this:
Hello World!
asdf //my input
asdf
Here are my files:
model.go
package models
type IndexModel struct {
Text string
}
func (m *IndexModel) InitModel() string {
return m.Text
}
func (m *IndexModel) SetText(newText string) {
m.Text = newText
}
view.go
package views
import "github.com/jufracaqui/mvc_template/app/models"
type IndexView struct {
Model models.IndexModel
}
func (v IndexView) Output() string {
return v.Model.Text
}
controller.go
package controllers
import "github.com/jufracaqui/mvc_template/app/models"
type IndexController struct {
Model models.IndexModel
}
func (c IndexController) ChangeText(userInput string) {
c.Model.SetText(userInput)
}
main.go:
package main
import (
"bufio"
"os"
"fmt"
"github.com/jufracaqui/mvc_template/app/controllers"
"github.com/jufracaqui/mvc_template/app/models"
"github.com/jufracaqui/mvc_template/app/views"
)
func main() {
handleIndex()
}
func handleIndex() {
model := models.IndexModel{
"Hello World!",
}
controller := controllers.IndexController{
model,
}
viewIndex := views.IndexView{
model,
}
fmt.Println(viewIndex.Model.Text)
reader := bufio.NewReader(os.Stdin)
text, _ := reader.ReadString('\n')
controller.ChangeText(text)
fmt.Println(viewIndex.Model.Text)
}
Edit:
How my code ended up after #JimB answer:
model.go:
package models
type IndexModel struct {
Text string
}
func (m *IndexModel) InitModel() string {
return m.Text
}
view.go:
package views
import "github.com/jufracaqui/mvc_template/app/models"
type IndexView struct {
Model *models.IndexModel
}
func (v IndexView) Output() string {
return v.Model.Text
}
controller.go:
package controllers
import "github.com/jufracaqui/mvc_template/app/models"
type IndexController struct {
Model *models.IndexModel
}
func (c IndexController) ChangeText(userInput string) {
c.Model.Text = userImput
}
main.go:
package main
import (
"bufio"
"os"
"fmt"
"github.com/jufracaqui/mvc_template/app/controllers"
"github.com/jufracaqui/mvc_template/app/models"
"github.com/jufracaqui/mvc_template/app/views"
)
func main() {
handleIndex()
}
func handleIndex() {
model := models.IndexModel{
"Hello World!",
}
m := &model
controller := controllers.IndexController{
m,
}
viewIndex := views.IndexView{
m,
}
fmt.Println(viewIndex.Model.Text)
reader := bufio.NewReader(os.Stdin)
text, _ := reader.ReadString('\n')
controller.ChangeText(text)
fmt.Println(viewIndex.Model.Text)
}
IndexController.ChangeText needs a pointer receiver, or IndexController.Model needs to be a pointer. You're calling SetText on a copy of the SetText value.
If you expect things to be mutable, it's much easier to consistently use pointers to structs throughout, and make explicit struct values the exception when you really need them.
I wonder how to replace *Type by ? What address has the structure inside?
//mycode.go
package main
import "fmt"
func out(k *Type) {
fmt.Println(k)
}
func main() {
type DataIP struct{ Title, Desc string }
Data := DataIP{
"Hello!",
"Hello GO!",
}
out(&Data)
}
You need to define the type DataIP outside of main() that the type is in the scope of the package and not just inside of the main function:
package main
import "fmt"
type DataIP struct{ Title, Desc string }
func out(k *DataIP) {
fmt.Println(k)
}
func main() {
Data := DataIP{
"Hello!",
"Hello GO!",
}
out(&Data)
}
https://play.golang.org/p/cUS6ttcUy-
I am not sure to understand your question.
If you want out to work only with structs of type DataIP:
simply define DataIP outside of main and use the signature func out(k *DataIP).
if what you want is to be able to pass any type of structure to out:
In golang, this sort of generic methods can be implemented using the interface type. As this answer explains, an interface is a container with two words of data:
one word is used to point to a method table for the value’s underlying type,
and the other word is used to point to the actual data being held by that value.
An interface can hold anything and is often used as a function parameter to be able to process many sort of inputs.
In your case, you can do:
func out(k interface{}) {
fmt.Println(k)
}
This will print &{Hello! Hello GO!}. In case you want the & to disappear (i.e. you always pass it pointers), you can use the reflect package to "dereference" k:
func out(k interface{}) {
fmt.Println(reflect.ValueOf(k).Elem())
}
which yields {Hello! Hello GO!}
Here is a playground example.
if what you want is to print the address of Data:
you can use the %p pattern with fmt.Printf:
fmt.Printf("%p", &Data) // 0x1040a130
Using the out function, you get:
func out(k interface{}) {
fmt.Printf("%p\n", k)
}
See this playground example