I am new of Go, and pretty curious of structs. Let's define a struct T
type T struct {
size int
}
I have seen different types of struct initialization. What are the differences?
new(T) // 1
T{size:1} // 2
&T{size:1} // 3
And the two types of method declarations:
func (r *T) area() int // 1
func (r T) area() int // 2
What should be the right way?
allocation
new and &T{size:1} returns *T
T{size:1} return T
The built-in function new takes a type T, allocates storage for a variable of that type at run time, and returns a value of type *T pointing to it. The variable is initialized as described in the section on initial values.
2.
The method set of any other named type T consists of all methods with receiver type T. The method set of the corresponding pointer type *T is the set of all methods with receiver *T or T (that is, it also contains the method set of T).
var pt *T
var t T
func (r *T) area() int
you can use pt.area() or t.area()
func (r T) area() int
you can use t.area(), can't use pt.area()
usually we use func(r *T) area() int
Here are different examples:
type Animal struct {
Legs int
Kingdom string
Carnivore bool
}
Initialization by reference
Return the pointer to the struct
var tiger = &Animal{4, "mammalia", true}
fmt.Println(tiger.Kingdom) // print "mammalia"
func changeKingdom(a *Animal) {
a.Kingdom = "alien" // modify original struct
}
changeKingdom(tiger)
fmt.Println(tiger.Kingdom) // print "alien"
Constructor New Initializaiton
Return a pointer with zero-ed values
var xAnimal = New(Animal)
fmt.Println(xAnimal.Kingdom) // print ""
fmt.Println(xAnimal.Legs) // print 0
fmt.Println(xAnimal.carnivore) // print false
changeKingdom(xAnimal)
fmt.Println(xAnimal.Kingdom) // print "alien"
Initialization by value (copy)
Return a separate copy of the original struct
var giraffe = Animal{4, "mammalia", false}
fmt.Println(giraffe.Kingdom) // print "mammalia"
func changeKingdom(a Animal) {
a.Kingdom = "extraterrestrial"
}
changeKingdom(giraffe)
fmt.Println(giraffe) // print "mammalia"
More often you'll deal with pointers when using structs than the copies.
Related
I've recently started learning Zig.
As a little project I wanted to implement a small QuickCheck [1] style helper library for writing randomized tests.
However, I can't figure out how to write a generic way to call a function with an arbitrary number of arguments.
Here's a simplified version that can test functions with two arguments:
const std = #import("std");
const Prng = std.rand.DefaultPrng;
const Random = std.rand.Random;
const expect = std.testing.expect;
// the thing we want to test
fn some_property(a: u64, b: u64) !void {
var tmp: u64 = undefined;
var c1 = #addWithOverflow(u64, a, b, &tmp);
var c2 = #addWithOverflow(u64, a, b, &tmp);
expect(c1 == c2);
}
// helper for generating random arguments for the function under test
fn gen(comptime T: ?type, rnd: Random) (T orelse undefined) {
switch (T orelse undefined) {
u64 => return rnd.int(u64),
f64 => return rnd.float(f64),
else => #compileError("unsupported type"),
}
}
/// tests if 'property' holds.
fn for_all(property: anytype) !void {
var rnd = Prng.init(0);
const arg_types = #typeInfo(#TypeOf(property)).Fn.args;
var i: usize = 0;
while (i < 100) {
var a = gen(arg_types[0].arg_type, rnd.random());
var b = gen(arg_types[1].arg_type, rnd.random());
var args = .{a, b}; // <-- how do I build args for functions with any number of arguments?
try #call(.{}, property, args);
i += 1;
}
}
test "test" {
try for_all(some_property);
}
I've tried a few different things, but I can't figure out how to get the above code to work for functions with any number of arguments.
Things I've tried:
Make args an array and fill it with an inline for loop. Doesn't work since []anytype is not a valid type.
Use a bit of comptime magic to build a struct type whose fields hold the arguments for #call. This hits a TODO in the compiler: error: TODO: struct args.
Write generic functions that return an appropriate argument tuple call. I don't really like this one, since you need one function for every arity you want to support. But it doesn't seem to work anyway since antype is not a valid return type.
I'm on Zig 0.9.1.
Any insight would be appreciated.
[1] https://hackage.haskell.org/package/QuickCheck
This can be done with std.meta.ArgsTuple (defined in this file of the zig standard library)
const Args = std.meta.ArgsTuple(#TypeOf(property));
var i: usize = 0;
while (i < 1000) : (i += 1) {
var args: Args = undefined;
inline for (std.meta.fields(Args)) |field, index| {
args[index] = gen(field.field_type, rnd.random());
}
try #call(.{}, property, args);
}
The way this works internally is it constructs a tuple type with #Type(). We can then fill it with values and use it to call the function.
I am trying to implement a method that returns a modified struct based on the original one, such as:
type Project struct {
Username string
Id uint
Alias string
Data *json.RawMessage
Scheme Scheme
}
func (p *Project) OmitUsername() *struct {
return &struct {
Id uint
Alias string
Data *json.RawMessage
Scheme Scheme
}{
p.Id,
p.Alias,
p.Data,
p.Scheme
})
}
And I get the following error:
models/project.go:22: syntax error: unexpected return
models/project.go:24: non-declaration statement outside function body
models/project.go:25: non-declaration statement outside function body
models/project.go:25: syntax error: unexpected string literal, expecting semicolon or newline
models/project.go:26: non-declaration statement outside function body
Any help would be appreciated.
With "truly" anonymous struct return value
If you want to use an anonymous struct return value, that's gonna look really ugly.
Why? Because when you define the return type, you have to describe the anonymous struct. And when you write a return statement, you have to provide the return value which will be a struct literal. A struct literal for an anonymous struct also has to describe the struct!
When you attempt to write this:
func (p *Project) OmitUsername() *struct {
// return somethig
}
This syntax is not what you think: it doesn't contain the struct definition. Basically in your example the first { is the opening bracket of the anonymous struct definition, and not the opening bracket of the function body. And as such, the subsequent return is interpreted as being inside the anonymous struct definition which is invalid syntax, this is exactly what the error message states too ("syntax error: unexpected return").
It should look like this:
func (p *Project) OmitUsername() *struct {
Id uint
Alias string
Data *json.RawMessage
Scheme Scheme
} {
// And now here comes the return statement
}
And if you also add the return statement which has to repeat the anonymous struct definition:
func (p *Project) OmitUsername() *struct {
Id uint
Alias string
Data *json.RawMessage
Scheme Scheme
} {
return &struct {
Id uint
Alias string
Data *json.RawMessage
Scheme Scheme
}{p.Id, p.Alias, p.Data, p.Scheme}
}
Yes, it's ugly. You can make it a little simpler by using named return value, and not returning a pointer, because zero value of pointers is nil, and to return something, you'd have to initialize it which would also involve repeating the anonymous struct! If you use a non-pointer, named return value, you will have a value of the anonymous struct right away, and you don't have to repeat the anonymous struct definition again, just assign values to its fields:
func (p *Project) OmitUsername2() (ret struct {
Id uint
Alias string
Data *json.RawMessage
Scheme Scheme
}) {
ret.Id = p.Id
ret.Alias = p.Alias
ret.Data = p.Data
ret.Scheme = p.Scheme
return
}
Using them:
p := Project{"Bob", 1, "bobie", nil, nil}
fmt.Println(p.OmitUsername())
fmt.Println(p.OmitUsername2())
Output (try these on the Go Playground):
&{1 bobie <nil> <nil>}
{1 bobie <nil> <nil>}
Still ugly...
With another named type, using embedding
...Best would be to provide another named type to return and not an anonymous struct. You may utilize embedding to make this solution practical and short:
type BaseProject struct {
Id uint
Alias string
Data *json.RawMessage
Scheme Scheme
}
type Project struct {
BaseProject
Username string
}
func (p *Project) OmitUsername() BaseProject {
return p.BaseProject
}
Using it:
p := Project{BaseProject{1, "bobie", nil, nil}, "Bob"}
fmt.Println(p.OmitUsername())
Output (try this on the Go Playground):
{1 bobie <nil> <nil>}
Note:
Embedding is not really necessary, but this way the fields of the embedded type (BaseProject) will be promoted and so you can refer to them like p.Id as if they were defined in Project. Defining it as a regular field would also work.
The Go Programming Language Specification
Keywords
The following keywords are reserved and may not be used as identifiers.
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
.
func (p *Project) OmitUsername() *struct {
}
struct is a reserved keyword.
Without more information about what you are trying to do, it's hard to know what you want, pehaps something like this?
package main
import (
"encoding/json"
)
type Scheme struct{}
type Project struct {
Id uint
Alias string
Data *json.RawMessage
Scheme Scheme
}
type UserProject struct {
Username string
Project
}
func (u *UserProject) GetProject() *Project {
return &u.Project
}
func main() {}
This question already has answers here:
How to initialize a nested struct?
(10 answers)
Closed 7 years ago.
Hi I am very new to Golang, please help me. I have defined a struct inside a struct. But I get an error when I try to initialise the main struct.
type DetailsFilter struct {
Filter struct {
Name string
ID int
}
}
var M map[string]interface{}
M = make(map[string]interface{})
M["Filter"] = map[string]interface{}{"Name": "XYZ", "ID": 5}
var detailsFilter = DetailsFilter{Filter: M["Filter"]}}
The error I get is : can not use (type interface {}) as type struct in field value : need type assertion.
Please suggest a way to initialise DetailsFilter.
I tried doing the method described in Initialize a nested struct in Golang, but even this is not working.
Unfortunately if the type of a struct field is an anonymous struct, at construction time you can only initialize it by "duplicating" the anonymous struct type (specifying it again):
type DetailsFilter struct {
Filter struct {
Name string
ID int
}
}
df := DetailsFilter{Filter: struct {
Name string
ID int
}{Name: "myname", ID: 123}}
fmt.Println(df)
Output:
{Filter:{Name:myname ID:123}}
Shorter Alternative
So instead I recommend not to initialize it at construction, but rather after the zero-valued struct has been created, like this:
df = DetailsFilter{}
df.Filter.Name = "myname2"
df.Filter.ID = 321
fmt.Printf("%+v\n", df)
Output:
{Filter:{Name:myname2 ID:321}}
Try it on the Go Playground.
Naming the anonymous struct type
Or don't use anonymous struct as field type at all, name the type like this:
type Filter struct {
Name string
ID int
}
type DetailsFilter struct {
Filter Filter
}
And then you can simply initialize it like this:
df := DetailsFilter{Filter: Filter{Name: "myname", ID: 123}}
fmt.Printf("%+v\n", df)
Output (try it on the Go Playground):
{Filter:{Name:myname ID:123}}
The type of M["Filter"] to the compiler is interface{}. The type to the runtime is map[string]interface{}. Neither of those is convertable to your anonymous struct type for the Filter field.
You should define a type for filter, or just not have it at all. Why not
type DetailsFilter struct {
Name string
ID int
}
M := make(map[string]*DetailsFilter)
M["Filter"] = &DetailsFilter{"Name": "XYZ", "ID": 5}
var detailsFilter = M["Filter"]
I am not sure why you need the nested anonymous struct at all. In general it is not needed to use interface{} unless you really need to. It is usually a sign you are fighting the type system instead of embracing it.
The reason You should not use an anonymous struct like that is that there is no clean way to intialize it. You have two options:
1- Repeat the type definition in the struct literal:
x := DetailsFilter{Filter: struct {
Name string
ID int
}{Name: "Foo", ID: 5}}
2- Set individual fields:
x := DetailsFilter{}
x.Filter.Name = "Foo"
x.Filter.ID = 5
It seems easier to create a real type for the nested field if you want to create them with struct literals.
I have an C struct (old library, blah blah blah) which contains an C string, now I need to convert CFString and Swift strings into this c string. Something like
struct Product{
char name[50];
char code[20];
}
So I'm trying to assign it as
productName.getCString(&myVarOfStructProduct.name, maxLength: 50, encoding: NSUTF8StringEncoding)
but the compiler is giving me the following error: cannot convert type (int8, int8, int8....) to [CChar].
A possible solution:
withUnsafeMutablePointer(&myVarOfStructProduct.name) {
strlcpy(UnsafeMutablePointer($0), productName, UInt(sizeofValue(myVarOfStructProduct.name)))
}
Inside the block, $0 is a (mutable) pointer to the tuple. This pointer is
converted to an UnsafeMutablePointer<Int8> as expected by the
BSD library function strlcpy().
It also uses the fact that the Swift string productName is automatically
to UnsafePointer<UInt8>
as explained in String value to UnsafePointer<UInt8> function parameter behavior. As mentioned in the comments in that
thread, this is done by creating a temporary UInt8 array (or sequence?).
So alternatively you could enumerate the UTF-8 bytes explicitly and put them
into the destination:
withUnsafeMutablePointer(&myVarOfStructProduct.name) {
tuplePtr -> Void in
var uint8Ptr = UnsafeMutablePointer<UInt8>(tuplePtr)
let size = sizeofValue(myVarOfStructProduct.name)
var idx = 0
if size == 0 { return } // C array has zero length.
for u in productName.utf8 {
if idx == size - 1 { break }
uint8Ptr[idx++] = u
}
uint8Ptr[idx] = 0 // NUL-terminate the C string in the array.
}
Yet another possible solution (with an intermediate NSData object):
withUnsafeMutablePointer(&myVarOfStructProduct.name) {
tuplePtr -> Void in
let tmp = productName + String(UnicodeScalar(0)) // Add NUL-termination
let data = tmp.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!
data.getBytes(tuplePtr, length: sizeofValue(myVarOfStructProduct.name))
}
Update for Swift 3:
withUnsafeMutablePointer(to: &myVarOfStructProduct.name) {
$0.withMemoryRebound(to: Int8.self, capacity: MemoryLayout.size(ofValue: myVarOfStructProduct.name)) {
_ = strlcpy($0, productName, MemoryLayout.size(ofValue: myVarOfStructProduct.name))
}
}
I have a std::vector of this struct:
struct MS
{
double aT;
double bT;
double cT;
};
which I want to use std::sort on as well as std::lower_bound/equal_range etc...
I need to be able to sort it and look it up on either of the first two elements of the struct. So at the moment I have this:
class MSaTLess
{
public:
bool operator() (const MS &lhs, const MS &rhs) const
{
return TLess(lhs.aT, rhs.aT);
}
bool operator() (const MS &lhs, const double d) const
{
return TLess(lhs.aT, d);
}
bool operator() (const double d, const MS &rhs) const
{
return TLess(d, rhs.aT);
}
private:
bool TLess(const double& d1, const double& d2) const
{
return d1 < d2;
}
};
class MSbTLess
{
public:
bool operator() (const MS &lhs, const MS &rhs) const
{
return TLess(lhs.bT, rhs.bT);
}
bool operator() (const MS &lhs, const double d) const
{
return TLess(lhs.bT, d);
}
bool operator() (const double d, const MS &rhs) const
{
return TLess(d, rhs.bT);
}
private:
bool TLess(const double& d1, const double& d2) const
{
return d1 < d2;
}
};
This allows me to call both std::sort and std::lower_bound with MSaTLess() to sort/lookup based on the aT element and with MSbTLess() to sort/lookup based on the bT element.
I'd like to get away from the functors and use C++0x lambdas instead. For sort that is relatively straightforward as the lambda will take two objects of type MS as arguments.
What about for the lower_bound and other binary search lookup algorithms though? They need to be able to call a comparator with (MS, double) arguments and also the reverse, (double, MS), right? How can I best provide these with a lambda in a call to lower_bound? I know I could create an MS dummy object with the required key value being searched for and then use the same lambda as with std::sort but is there a way to do it without using dummy objects?
It's a little awkward, but if you check the definitions of lower_bound and upper_bound from the standard, you'll see that the definition of lower_bound puts the dereferenced iterator as the first parameter of the comparison (and the value second), whereas upper_bound puts the dereferenced iterator second (and the value first).
So, I haven't tested this but I think you'd want:
std::lower_bound(vec.begin(), vec.end(), 3.142, [](const MS &lhs, double rhs) {
return lhs.aT < rhs;
});
and
std::upper_bound(vec.begin(), vec.end(), 3.142, [](double lhs, const MS &rhs) {
return lhs < rhs.aT;
});
This is pretty nasty, and without looking up a few more things I'm not sure you're actually entitled to assume that the implementation uses the comparator only in the way it's described in the text - that's a definition of the result, not the means to get there. It also doesn't help with binary_search or equal_range.
It's not explicitly stated in 25.3.3.1 that the iterator's value type must be convertible to T, but it's sort of implied by the fact that the requirement for the algorithm is that T (in this case, double) must be LessThanComparable, not that T must be comparable to the value type of the iterator in any particular order.
So I think it's better just to always use a lambda (or functor) that compares two MS structs, and instead of passing a double as a value, pass a dummy MS with the correct field set to the value you're looking for:
std::upper_bound(vec.begin(), vec.end(), MS(3.142,0,0), [](const MS &lhs, const MS &rhs) {
return lhs.aT < rhs.aT;
});
If you don't want to give MS a constructor (because you want it to be POD), then you can write a function to create your MS object:
MS findA(double d) {
MS result = {d, 0, 0};
return result;
}
MS findB(double d) {
MS result = {0, d, 0};
return result;
}
Really, now that there are lambdas, for this job we want a version of binary search that takes a unary "comparator":
double d = something();
unary_upper_bound(vec.begin(), vec.end(), [d](const MS &rhs) {
return d < rhs.aT;
});
C++0x doesn't provide it, though.
The algorithms std::sort, std::lower_bound, and std::binary_search take a predicate that compares two elements of the container. Any lambda that compares two MS objects and returns true when they are in order should work for all three algorithms.
Not directly relevant to what you're saying about lambdas, but this might be an idea for using the binary search functions:
#include <iostream>
#include <algorithm>
#include <vector>
struct MS
{
double aT;
double bT;
double cT;
MS(double a, double b, double c) : aT(a), bT(b), cT(c) {}
};
// template parameter is a data member of MS, of type double
template <double MS::*F>
struct Find {
double d;
Find(double d) : d(d) {}
};
template <double MS::*F>
bool operator<(const Find<F> &lhs, const Find<F> &rhs) {
return lhs.d < rhs.d;
}
template <double MS::*F>
bool operator<(const Find<F> &lhs, const MS &rhs) {
return lhs.d < rhs.*F;
}
template <double MS::*F>
bool operator<(const MS &lhs, const Find<F> &rhs) {
return lhs.*F < rhs.d;
}
int main() {
std::cout << (Find<&MS::bT>(1) < Find<&MS::bT>(2)) << "\n";
std::cout << (Find<&MS::bT>(1) < MS(1,0,0)) << "\n";
std::cout << (MS(1,0,0) < Find<&MS::bT>(1)) << "\n";
std::vector<MS> vec;
vec.push_back(MS(1,0,0));
vec.push_back(MS(0,1,0));
std::lower_bound(vec.begin(), vec.end(), Find<&MS::bT>(0.5));
std::upper_bound(vec.begin(), vec.end(), Find<&MS::bT>(0.5));
}
Basically, by using Find as the value, we don't have to supply a comparator, because Find compares to MS using the field that we specify. This is the same kind of thing as the answer you saw over here: how to sort STL vector, but using the value rather than the comparator as in that case. Not sure if it'd be all that great to use, but it might be, since it specifies the value to search for and the field to search in a single short expression.
I had the same problem for std::equal_range and came up with an alternative solution.
I have a collection of pointers to objects sorted on a type field. I need to find the find the range of objects for a given type.
const auto range = std::equal_range (next, blocks.end(), nullptr,
[type] (Object* o1, Object* o2)
{
return (o1 ? o1->Type() : type) < (o2 ? o2->Type() : type);
});
Although it is less efficient than a dedicated predicate as it introduces an unnecessary nullptr test for each object in my collection, it does provide an interesting alternative.
As an aside, when I do use a class as in your example, I tend to do the following. As well as being shorter, this allows me to add additional types with only 1 function per type rather then 4 operators per type.
class MSbTLess
{
private:
static inline const double& value (const MS& val)
{
return val.bT;
}
static inline const double& value (const double& val)
{
return val;
}
public:
template <typename T1, typename T2>
bool operator() (const T1& lhs, const T2& rhs) const
{
return value (t1) < value (t2);
}
};
In the definition of lower_bound and other STL Algorithms the Compare function is such that the first type must match that of the Forward Iterator and the second type must match that of T (i.e., of the value).
template< class ForwardIt, class T, class Compare >
ForwardIt lower_bound( ForwardIt first, ForwardIt last, const T& value, Compare comp );
So one indeed can compare things from different objects (doing what the other response called an Unary Comparator). In C++11 :
vector<MS> v = SomeSortedVectorofMSByFieldaT();
double a_key;
auto it = std::lower_bound(v.begin(),
v.end(),
a_key,
[]{const MS& m, const double& a) {
m.aT < a;
});
And this can be used with other STL algorithm functions as well.