This question already has answers here:
Private fields and methods for a struct
(6 answers)
Closed 6 months ago.
I have the following modules
package apack
type Something structs{
a string
b string
}
var FullList []Something
func Complete() []Something {
FullList = append(FullList, Something{
a: 'first',
b: 'second'
})
return FullList
}
Now the following main
import "something/apack"
func main() {
re = apack.Complete()
for _,s := range re {
s1 := apack.Something(s)
fmt.Println(s1)
}
}
when I run it I get the following:
{first second}
but if I do something like
fmt.Println(s1.a)
I get the following error:
./main.go:70:19: s1.a undefined (type apack.Something has no field or method a)
Is it possible to be able to access structs from another package?
I think map should work, just unsure how for this case.
Thanks
Yes it's possible, just make the fields of your struct (that you want to access from the other package) exported:
type Something struct {
A string
b string
}
Then you can access all the exported fields from the struct so fmt.Println(s1.A) in the other package code will now work, but fmt.Println(s1.b) will not work as b is still an unexported field.
Also, here is a very simple lesson from A Tour of Go (which I also recommend as a whole) about exported names.
Related
This question already has an answer here:
cannot infer V: infer type parameter from constraint implementation
(1 answer)
Closed 5 months ago.
Say I have the following code:
type Getter[T any] interface {
Get() T
}
type Wrapper[T any] struct {
a T
}
func (s Wrapper[T]) Get() T {
return s.a
}
Here, you can say that Wrapper[T] implements Getter[T] - since it implements Get() T which is the only requirement.
Now, I have a function that needs to take a Getter[T] in order to return the internal value...
func Return[T any](i Getter[T]) T {
return i.Get()
}
var s1 = Wrapper[int]{
a: 5,
}
Here, Return just gets the value inside - so the expectation is that when I pass in s1, I should get 5 in return.
var s2 = Return(s1) // type Wrapper[int] of s1 does not match Getter[T] (cannot infer T)
...instead, I get that error. Now, there is an easy workaround here...
func (s Wrapper[T]) Getter() Getter[T] {
return s
}
var s2 = Return(s1.Getter())
This ends up working. Getter() does nothing but return itself - functionally speaking, s1 and s1.Getter() should be identical here - and yet it doesn't work. T can be inferred in the method, but not as a parameter.
My question is this: Am I doing something wrong here - or is this just a part of Go? For this example to work, do I need to add a dummy method just to help the compiler - or am I missing something?
You do not need to add methods to Wrapper, but if type inference does not succeed (the compiler can't infer all types), you have to provide the types for the type parameters explicitly, like this:
var s2 = Return[int](s1)
The Return() function has a type parameter, if you provide the type for T explicitly (int here), then the compiler will be able to validate that s1 does indeed implement the Getter[int] interface. Try it on the Go Playground.
This question already has answers here:
How to assign or return generic T that is constrained by union?
(2 answers)
Closed 5 months ago.
I read a lot of docs but I couldn't find if I'm able to do it.
Is there a way to do something like this in Go without use an interface as return type?
Playground example
package main
import "fmt"
type Foo struct {
Id uint
FooField string
}
type Bar struct {
Id uint
BarField string
}
type Model interface {
Foo | Bar
}
func build[T Model](s string) T {
if s == "foo" {
fmt.Println(s)
return Foo{}
}
fmt.Println(s)
return Bar{}
}
func main() {
build("foo")
}
No, at least not how you've shown here.
Go is a statically typed language, meaning that the semantic data types of values do not depend on any dynamic values in the program.
Interfaces are not an exception to this, but an extension. From the language specification (abridged):
The static type (or just type) of a variable is the type given in its declaration. Variables of interface type also have a distinct dynamic type, which is the (non-interface) type of the value assigned to the variable at run time.
Here's an alternate version that would work.
func build[T Model]() T {
var x T
return x
}
func main() {
// VVV explicitly passing the type parameter, not a string
build[Foo]()
}
The reason why this is valid and yours isn't, is because now the return type only depends on the type parameter provided, which is always static. Type parameters are often omitted entirely when they can be inferred by the compiler, but in cases like this, it's most correct to list them explicitly.
This question already has answers here:
Invoking struct function gives "cannot refer to unexported field or method"
(2 answers)
Closed 2 years ago.
Please help to understand, how I can return from function not only values from structure but with their names?
Example my arg.go
package flags
import (
"flag"
)
type FlagsStruct struct {
argTest1 string
argTest2 string
}
func GetInitFlags() *FlagsStruct {
Flags := new(FlagsStruct)
flag.StringVar(&Flags.argTest1, "test1", "test1", "c")
flag.StringVar(&Flags.argTest2, "test2", "test2", "t")
flag.Parse()
return Flags
}
It's working only with keys, for example in my main function I trying to print and it's working:
fmt.Print(*inputFlags)
{test1 test2}
But how I can pass taht can print something like this?
fmt.Printf(inputFlags.argTest2)
./main.go:25:24: inputFlags.argTest2 undefined (cannot refer to
unexported field or method argTest2)
Make your argument names start with a capital letter (ArgTest2). See this question for more details.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I am working on a demo project to understand GO language. I have defined one interface and 2 struct type. Also, I have defined an array of interfaces. Depending on the user input, I define each element within the array as a type of struct. During the data manipulation, I want to check the type of the struct defined on the array.
I have tried to use reflect, but unfortunately it did not worked. Also other methods on internet did not worked. I received messages such as panic or json cannot Unmarshal.
type Main_interface interface {
}
type Struct1 struct {
Index int
ID int
Name string
}
type Struct2 struct {
Index int
Timestamp string
Temporary_ID int
}
var MyArray []Main_interface
//...
NewStruct1Block := generateStruct1Block(...)
MyArray = append(MyArray, NewStruct1Block)
//...
NewStruct2Block := generateStruct2Block(...)
MyArray = append(MyArray, NewStruct2Block)
UPDATE: I want to be able to check the kind of struct implements the interface at runtime, depending on the user input.
Your array can be heteregenious, that is, it can contain elements of different types. You can't ensure (at compile time) that all elements are of the same type.
That said, you can check a single element using the type cast syntax.
You have three options:
Option 1: Check against a specific type
var unknown Main_Interface = getSomethingSomewhere()
result, ok := unknown.(Struct1);
if ok {
// result has type `Struct1`
}
Option 2: Use a switch statement to cover multiple types (already presented in another answer)
switch t := unknown.(type) {
case Struct1:
// t has type `Struct1` within this block (at compile time)
case Struct2:
// t has type `Struct2` within this block (at compile time)
default:
// neither Struct1 no Struct2
}
Option 3: compare against another type at runtime.
Note that types returned by reflect.TypeOf are comparable using the == operator, as documented here:
https://golang.org/pkg/reflect/#Type
Type values are comparable, such as with the == operator, so they can be used as map keys. Two Type values are equal if they represent identical types.
So we can do something like this:
var s1 Struct1 // empty struct
var s2 Struct2 // empty struct
if reflect.TypeOf(unknown) == reflect.TypeOf(s1) {
// unknown holds an s1 instance
}
But this is obviously not useful when you can just do the compile time check. Instead, you can compare two unknowns to check if they are the same:
var unknown1 Main_Interface = getSomethingSomewhere()
var unknown2 Main_Interface = getSomethingSomewhereElse()
if reflect.TypeOf(unknown1) == reflect.TypeOf(unknown2) {
// they are the same type
}
You need to use type assestion as below:
var MyArray []Main_interface
NewStruct1Block := Struct1{}
NewStruct2Block := Struct2{}
MyArray = append(MyArray, NewStruct1Block)
MyArray = append(MyArray, NewStruct2Block)
fmt.Printf("%v", MyArray)
switch t := MyArray[0].(type) {
case Struct1:
fmt.Printf("%v", t)
t.ID = 1
case Struct2:
fmt.Printf("%v", t)
t.Timestamp = "A"
default:
fmt.Print("unknown")
}
Working code here:
https://play.golang.org/p/OhpBDJu_q2x
This question already has answers here:
Go Unmarshaling YAML into struct
(2 answers)
Closed 4 years ago.
Im trying to convert a yaml data into a struct and print it. The output I get for this program is empty.
package main
import (
"fmt"
"gopkg.in/yaml.v2"
)
type example struct {
variable1 string
variable2 string
}
func main() {
var a example
yaml.Unmarshal([]byte("variable1: asd\nvariable2: sdcs"), &a)
fmt.Println(a.variable1)
}
The documentation for Unmarshal states that
Struct fields are only unmarshalled if they are exported (have an upper case first letter) and are unmarshalled using the field name lowercased as the default key.
So capitalizing your struct elements is the right thing to do.
type example struct {
Variable1 string
Variable2 string
}