Golang: How to append pointer to slice to slice? - pointers

I'm a Golang newbie but I thought I had got the essentials of pointers and references straight, but apparently not:
I have a method that must return a []github.Repository, which is a type from the Github client in go.
The API call returns the results paginated so I must cycle until there's no more results, and add the result of each call to the allRepos variable, and return that. Here's what I have so far:
func (s *inmemService) GetWatchedRepos(ctx context.Context, username string) ([]github.Repository, error) {
s.mtx.RLock()
defer s.mtx.RUnlock()
opt := &github.ListOptions{PerPage: 20}
var allRepos []github.Repository
for {
// repos is of type *[]github.Repository
repos, resp, err := s.ghClient.Activity.ListWatched(ctx, "", opt)
if err != nil {
return []github.Repository{}, err
}
// ERROR: Cannot use repos (type []*github.Repository) as type github.Repository
// but dereferencing it doesn't work, either
allRepos = append(allRepos, repos...)
if resp.NextPage == 0 {
break
}
opt.Page = resp.NextPage
}
return allRepos, nil
}
My question: how can I append the results of each call and return a result of type []github.Repository?
Also, why doesn't dereferencing work here? I've tried replacing allRepos = append(allRepos, repos...) with allRepos = append(allRepos, *(repos)...) but I get this error message:
Invalid indirect of (repos) (type []*github.Repository)

Well, something is not okay here:
You say in the comment that "repos is of type *[]github.Repository" but the compiler's error message indicates that repos is of type []*Repository". The compiler is never (except when buggy) wrong.
Note that *[]github.Repository and []*Repository are completely different types, especially the second is not a slice of Repositories and you cannot (really, there is no way) dereference these pointers during append(): You have to write a loop and dereference each slice item and append one by one.
What is strange too: github.Repository and Repository seem to be two different types one from package github, the other from the current package. Again, you'll have to get that straight too.
Note that there are no references in Go. Stop thinking about these immediately: This is a concept from other languages which is not helpful (as inexistent) in Go.

In your example the dereferencing is not correct. You should make it like this:
allRepos = append(allRepos, *repos...)
Here a simple example with dereferencing a pointer to a slice of string. https://play.golang.org/p/UDzaG5z8Pf

Related

ocmock's invokeBlockWithArgs using a nil argument

is there any way to invoke a block with nil as a given argument, given that the invokeBlockWithArgs: requires the args to be nil-terminated?
example method definition in a mocked object:
- (void)methodWithCompletion:(void(^)(NSString*, NSError* )) completionBlock;
The given mockObject should call:
completionBlock(#"foo", nil);
however, with invokeBlockWithArgs:
OCMStub([mockObj methodWithCompletion:([OCMArg invokeBlockWithArgs:#"foo", nil, nil])]);
Method fails, with too few arguments; obviously with nil being the termination, it doesn't recognize the second parameter to the block should be nil.
I haven't tested it but theoretically passing [NSNull null] should work.
Adding to the existing answers here, passing [NSNull null] does what you want in this case, which is passing nil as the param there.
I had a case (shown below) where my logic tested the existence of an error object OR my array was empty, and wanted my test to cover both cases and was afraid I'd only be able to test one case
if (error || array.count == 0) {
// fail here
}
Here is my test OCMock code:
NSArray *emptyArray = #[];
OCMStub([requestMock loadListWithCompletion:([OCMArg invokeBlockWithArgs:emptyArray, [NSNull null], nil])]);
...and in the actual invocation of that method, the error param (that I passed [NSNull null] into) was indeed nil, so the logic fell through to the empty array and the error case was still handled.
You can pass [NSNull null]. I just tested, it works.

Reflect on Time type in go

I am trying to write a csv parser using the example provided here. It works great for all native types but I am having trouble with any structs that contain a timestamp of type time.Time. It exits with an error of "cannot convert this type".
This is the code.
//For each field in a given struct...
//Get a field
val := sv.Field(i)
// this is necessary because Kind can't tell
// distinguish between a primitive type
// and a type derived from it. We're looking
// for a Value interface defined on
// the pointer to this value
_, ok := val.Addr().Interface().(Value)
if ok {
val = val.Addr()
kind = value_k
} else {
switch Kind {
case reflect.Int, reflect.Int16, reflect.Int8,
reflect.Int32, reflect.Int64:
kind = int_k
case reflect.Uint, reflect.Uint16, reflect.Uint8,
reflect.Uint32, reflect.Uint64:
kind = uint_k
case reflect.Float32, reflect.Float64:
kind = float_k
case reflect.String:
kind = string_k
default:
// Kind is Struct here
kind = value_k
_, ok := val.Interface().(Value)
if !ok {
err = os.NewError("cannot convert this type ")
this = nil
return
}
}
}
What this code does is take an interface and a reader. It attempts to match the field headers in the reader (csv file) with field names in the interface. It also reflects on the interface (struct) and collects positional a type information for later setting the fields in the iterator. It is this step that is failing for non-native types.
I've tried a few methods to work around this but the only thing that seems to work is changing the timestamp to a string. I am undoubtedly missing something and would greatly appreciate some guidance.

How would you access the underlying array passed to a function expecting an empty interface in Go?

So let's say that we have a function of the following form:
func WorkMagic(obj interface{}) interface{} {
switch t := obj.(type) {
case string:
// Do string magic
default:
// Do slice magic
}
...
}
I am expecting obj to be either a string or a slice, which I can ascertain via the switch. In the case of a slice, I want to be able to do ordering work on any arbitrary slice, regardless of type. Seems like the best way to accomplish this is using the unsafe package in a similar fashion to that discussed in this article.
Here however, the function accepts a specific type of slice ([]string), whereas I would like to be able to work on any slice. So the question is, given that I am accepting an empty interface as input, how might I access the underlying slice / array using unsafe.Pointer so as to be able to loop through and modify which value is associate with which index?
You'll want to use reflection. It enables you to work generically without giving up type and memory safety like unsafe would. Read the Go blog's Laws of Reflection.
func actOnSlices(i interface{}) {
v := reflect.ValueOf(i)
for v.Kind() == reflect.Ptr { // dereference pointers
v = v.Elem()
}
if v.Kind() != reflect.Slice { // ensure you actually got a slice
panic("given argument is not a slice")
}
// do slice stuff
}
Edit to answer your second question:
Yes – this can be done: elements of a slice are adressable and hence settable. See the following working example:
package main
import (
"fmt"
"reflect"
)
func main() {
s := []string{"foo", "bar"}
fmt.Println(swapIndexes(s, 0, 1)) // prints [bar foo]
}
func swapIndexes(i interface{}, x, y int) interface{} {
v := reflect.ValueOf(i)
for v.Kind() == reflect.Ptr { // dereference pointers
v = v.Elem()
}
if v.Kind() != reflect.Slice { // ensure you actually got a slice
panic("given argument is not a slice")
}
t := v.Index(x).Interface()
v.Index(x).Set(v.Index(y))
v.Index(y).Set(reflect.ValueOf(t))
return v.Interface()
}
Edit to answer your third question:
The unsafe package is not something you'll encounter much in user-land code. It exists to implement certain features (e.g. reflection, C interaction) that need to circumvent Go's safety guarantees to work. Using unsafe is unsafe, as the name suggests, because you can mess up big time without even realizing. By using unsafe, you're incurring in a big trade-off, so it better be worth it. Quoting #twotwotwo:
The downside of unsafe is that if you mess up you're in the old days of segfaults, memory corruption, and buffer-overflow security holes.
Also, as #twotwotwo suggested; it's more "Go-like" to repeat code than using reflection to achieve genericity.
To Go's type-system, []string and []int are two completely separate and unrelated types. just as int and string would be. The relation (both are slices) is obvious only to the programmer. There is no way of expressing "a slice" without saying a slice of what.

How to use run time error in golang?

I am trying to download something from 3 servers. My idea is if the first server is closed,it will use the second server. I noticed,if the first server has been closed, it will created a run time error.I want to know how to use this error,what i need is like this:
if run time err!=nil{do something}
i am new to golang,hope someone can help me
thank you
To elaborate on what FUZxxl explained, go makes a distinction between an error (something which could go wrong indeed went wrong) and an exception (something which could not possibly go wrong actually went wrong).
The distinction can sometimes be subtle (as it relies on what is 'unexpected'), but it can also be clearer than the 'everything is an exception' that you see in other languages.
For instance, consider integers which might overflow. One possibility is to consider it a 'normal' behaviour, which should be handled appropriately:
func safe_add(x, y uint32) (uint32, error) {
z := x + y
if z < x || z < y {
return 0, fmt.Errorf("Integer overflow")
}
return z, nil
}
Another is to consider it 'never happens' and have the runtime panic in the unlikely case when it happens against all odds:
func panic_add(x, y uint32) uint32 {
z, err := safe_add(x, y)
if err != nil {
panic(err)
}
return z
}
(Note that I use my own 'safe_add' here, but you don't have to of course)
The main difference is in the way you handle the error afterwards. Adding a number to itself until it overflows with errors gives:
func safeloop(u uint32) {
var err error
for {
if u, err = safe_add(u, u); err != nil {
fmt.Println(err)
return
} else {
fmt.Println(u)
}
}
}
While handling panics uses the recover built-in function:
func panicloop(u uint32) {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
}()
for {
u = panic_add(u, u)
fmt.Println(u)
}
}
(full examples on the playground)
Note that the panic version has a much simpler loop, as you basically never expect anything to go wrong and never check for errors. The counterpart for this is that the way to handle panics is quite cumbersome, even for a very simple example like this. You defer a function which will call recover and capture the error when it arises and breaks out of the function. When your code becomes more complex, tracking exactly where/how the panic arose and acting on it accordingly can become much more complex than checking for errors in places where they could arise, with the result, err := func_which_may_fail(...) pattern.
You can even alternate between panics, recover which return errors, errors converted to panics, ... but this is (understandably) considered poor design.
There are some good resources on error handling and panics on the go blog. The specs is a good read to.
In your case, as you expect 'the server is closed' to be a pretty frequent behaviour, you should definitely go the error way, as FUZxxl suggested, but I hope this might be useful to you (or others) to understand how error handling works in Go.
When you do something which could go wrong, you get an error object.
bytes, err = stream.Read(buffer)
To check whether what you tried actually went wrong, compare the error object against nil. nil signalizes that no error has happened. In the case the error is not nil, you can do something about it.
if err != nil {
// insert error handling here
}

Go : doubly linked list implementing panic error

Correction:
Link #1 http://play.golang.org/p/CKRNyWYF8X
Link #2 http://play.golang.org/p/oT2yKzFwep
From the first link,
I am sure that the panic error comes from this
func (A *DoublyLinkedList) AddHead(input_value interface{}) {
temp_node := &Node{value: input_value, prev: nil, next: A.head}
original_head_node := A.head
original_head_node.prev = temp_node
A.length++
}
But when I use this for doubly linked list, it panics little later. And still fails because this one below does not connect the original head with previous pointer.
func (A *DoublyLinkedList) AddHead(input_value interface{}) {
A.head = NewNode(input_value, nil, A.head)
A.length++
}
This is the one. This one has the similar problem.
cannot assign to target_node.GetPrevNode().GetNextNode()
Does go not support pointer reference this way? I did fix this just assigning a new variable every time I need to get the pointer. But my first question on the top still does not compile.
In short, how do I connect the doubly linked list when adding a new element in Go?
You need to initialize the properties inside the DoublyLinkedList. It seems to me, you are currently creating a reference to it in NewDoublyLinkedList() with 2 nil properties.
type DoublyLinkedList struct {
head *Node // nil
tail *Node // nil
length int
}
And when doing this
original_head_node := A.head // A.head == nil
original_head_node.prev = temp_node // You are trying to access a property in nil

Resources