简体   繁体   中英

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  

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, eg:

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?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM