doumi7861
doumi7861
2016-12-27 21:13
浏览 83

Golang不能用作类型struct数组或slice文字

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  
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • douyuai8994
    douyuai8994 2016-12-27 21:20
    已采纳

    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?

    点赞 评论

相关推荐