Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang cannot use as type struct array or slice literal

I'm trying to write a function in Go that takes a JSON with URLs of a directory and perform BFS to find files in that directory. When I find a JSON that is a directory, the code makes a URL and should enqueue that URL. When I try to create the struct in the append() in the loop, I get errors.

type ContentResp []struct {
    Name string `json:"name"`
    ContentType string `json:"type"`
    DownloadURL string `json:"download_url"`
}
...

var contentResp ContentResp
search(contentQuery, &contentResp)

for _, cont := range contentResp {
        append(contentResp, ContentResp{Name:cont.Name, ContentType:"dir", DownloadURL:cont.contentDir.String()})
}

./bfs.go:129: undefined: Name
./bfs.go:129: cannot use cont.Name (type string) as type struct { Name string "json:\"name\""; ContentType string "json:\"type\""; DownloadURL string "json:\"download_url\"" } in array or slice literal
./bfs.go:129: undefined: ContentType
./bfs.go:129: cannot use "dir" (type string) as type struct { Name string "json:\"name\""; ContentType string "json:\"type\""; DownloadURL string "json:\"download_url\"" } in array or slice literal
./bfs.go:129: undefined: DownloadURL
./bfs.go:129: cannot use cont.contentDir.String() (type string) as type struct { Name string "json:\"name\""; ContentType string "json:\"type\""; DownloadURL string "json:\"download_url\"" } in array or slice literal  
like image 261
Soubriquet Avatar asked Dec 27 '16 21:12

Soubriquet


People also ask

What is struct literal in Golang?

A struct literal denotes a newly allocated struct value by listing the values of its fields. You can list just a subset of fields by using the Name: syntax. (And the order of named fields is irrelevant.) The special prefix & returns a pointer to the struct value.

What is composite literal?

A composite literal is a concise syntax to initialize any composite type with the values you want. Rather than declare an array and assign elements one by one, Go's composite literal syntax will declare and initialize an array in a single step, as shown in the following listing.

What is a slice literal?

A slice literal is like an array literal without the length. This is an array literal: [3]bool{true, true, false} And this creates the same array as above, then builds a slice that references it: []bool{true, true, false}


1 Answers

Your ContentResp type is a slice, not a struct, yet you're treating it as a struct when you use a composite literal trying to create a value of it:

type ContentResp []struct {
    // ...
}

More precisely it's a slice of a type which is an anonymous struct. Creating values of anonymous structs are unpleasant, so instead you should create (name) a type being only the struct, and use a slice of this, e.g.:

type ContentResp struct {
    Name        string `json:"name"`
    ContentType string `json:"type"`
    DownloadURL string `json:"download_url"`
}

var contentResps []ContentResp

Further issues:

Let's examine this loop:

for _, cont := range contentResp {
    append(contentResp, ...)
}

The code above ranges over a slice, and inside it it tries to append elements to the slice. 2 issues with this: append() returns the result which must be stored (it might even have to allocate a new, bigger backing array and copy existing elements over, in which case the result slice will point to a completely different array and the old one should be abandoned). So it should be used like this:

    contentResps = append(contentResps, ...)

Second: you shouldn't change the slice you're ranging over. The for ... range evaluates the range expression once (at most), so you changing it (adding elements to it) will have no effect to the iterator code (it will not see the slice header changes).

If you have such a case where you have "tasks" to be completed, but during execution new tasks may arise (to be completed, recursively), a channel is a much better solution. See this answer to get a feeling of channels: What are golang channels used for?

like image 147
icza Avatar answered Sep 17 '22 08:09

icza