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.
Related
I am really new to golang and I am trying to see how encapsulation really works in go.
I have the following structure
-- package a
-a_core.go
-a.go
-models.go
-- main.go
In models.go I have structs for request and responses for an api call,
a.go has an empty struct, which is private and a public interface, which I want to expose with various methods
a_core.go just has some business logic which would be called in my interface implementation
Then, I have a main.go where I just call the public interface.
code in a.go
package a
type myFunction struct{}
type MyFunc interface {
Create(myData *MyData) (*MyData, error)
Fetch(test string)
Delete(test string)
}
//Concrete implementations that can be accessed publicly
func (a *myFunction) Create(data *MyData) (*MyData, error) {
return nil, nil
}
func (a *myFunction) Fetch(test string) {
}
func (a *myFunction) Delete(test string) {
}
In main.go, I call the interface my first create the MyData pointer with values
data := &a.MyData{
/////
}
result, err := a.MyFunc.Create(data)
I get the following error when I do this,
too few arguments in call to a.MyFunc.Create
cannot use data (variable of type *a.MyData) as a.MyFunc value in argument to a.MyFunc.Create: missing method CreatecompilerInvalidIfaceAssign
Please what am I doing wrong?
Here is an example
Note that names in uppercase are public, in lowercase private (see https://tour.golang.org/basics/3 )
./go-example/main.go
package main
import "go-example/animal"
func main() {
var a animal.Animal
a = animal.Lion{Age: 10}
a.Breathe()
a.Walk()
}
./go-example/animal/animal.go
package animal
import "fmt"
type Animal interface {
Breathe()
Walk()
}
type Lion struct {
Age int
}
func (l Lion) Breathe() {
fmt.Println("Lion breathes")
}
func (l Lion) Walk() {
fmt.Println("Lion walk")
}
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:}}
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
I'm wondering if it's possible to get the method fields from a typed function using reflection or by other means.
The problem that I'm trying to solve is that I have a method which accepts a function of specific type but I need to actually transport different types and based on the type provided to execute operations. I'm aware that I could use an interface{} value as receiver but I don't want to loose the type checking on the calling function ("GetIt")
package main
type ttp struct {
Coupons string
}
func (m ttp) GetIt(x string) {
if m.Coupons != "" {
print(m.Coupons)
}
}
func calculate(mth func(s string)){
//perform calculations and update the Coupon field
mth.Cupons = "one coupon" // is not working :(
// execute it again with the processed value
mth.GetIt() // is not working
}
func main() {
m := ttp{Coupons: "something"}
calculate(m.GetIt)
}
Play
well this does not answer your exact question but it should solve your problem and cleanup the logic: push the calculate method inside the type and use a interface
https://play.golang.org/p/On_AigRYW6
package main
import "fmt"
type Computer interface {
Compute(string)
}
type myp struct {
Coupons string
}
// myp implements Computer
func (m *myp) Compute(x string) {
m.GetIt(x)
fmt.Println("myp")
}
type ttp struct {
Various string
}
// ttp implements Computer
func (m *ttp) Compute(x string) {
m.GetIt(x)
fmt.Println("ttp")
}
func (m myp) GetIt(x string) {}
func (m ttp) GetIt(x string) {}
func main() {
m := &myp{Coupons: "something"}
t := &ttp{Various: "various stuff"}
var stuff = []Computer{m, t}
for _, c := range stuff {
c.Compute("s")
}
}
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()
}