func WaitForWorkers(){
var wg sync.WaitGroup
for range{
...
wg.Add(1)
go gol(...)
}
wg.Wait()
}
func gol(...){
...
wg.Done()
}
myTemplate.Delims("<<", ">>")
{{ template "templates/header.html" . }} //<-вот здесь ошибка
t, err := template.ParseFiles( "templates/content.html" , "templates/header.html", "templates/footer.html")
{{ template "header" . }}
text
{{ template "footer" . }}
{{define "header"}}
<!DOCTYPE html>
<html>
<head>
<title>text</title>
</head>
<body>
{{end}}
{{define "footer"}}
</body>
</html>
{{end}}
type MyMap map{Key]*Value
type Value struct{
sync.RWMutex
value
}
sync.atomic
type M map[Key]*unsafe.Pointer
type Value *YorValueType
var old, changed Value
m := make(M)
v := unsafe.Pointer(old)
m[key] = &v
old = (*Value)(*m[key])
changed := DoSomething(*old)
atomic.StorePointer(m["foo"], unsafe.Pointer(&changed)) //Здесь атомарно подменяется ссылка
[]map[Key]Value
илиmap[Key1]struct{
sync.RWMutex
map[key2]Value
}
ReportChan := make(chan os.FileInfo)
go func(inspectdir string) {
for range time.Tick(time.Second) {
if err := filepath.Walk(inspectdir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if time.Now().Sub(info.ModTime()) < time.Second {
ReportChan <- info
}
return nil
}); err != nil {
log.Log(err.Error()) //do something with err
}
}
}("/dir/to/inspect")
for modifiedFile : = range <-ReportChan{
//do something with modifiedFile
}
config := &oauth2.Config{
ClientID: "YourClientID",
ClientSecret: "YourClientSecret",
Scopes: []string{scope},
Endpoint: oauth2.Endpoint{
AuthURL: "YourAuthURL",
TokenURL: "YourTokenURL",
},
RedirectURL: "YourredirectUri",
}
token:=oauth2.Token{
AccessToken: "Youraccess token"
TokenType "Bearer",
}
/*
или если у вас на руках не access token а authorization code
то можно попробовать
token:=config.Exchange(oauth2.NoContext, "authorization code")
*/
client, err:=config.Client(oauth2.NoContext, token)
r.File
, однако при надобности название типа можно использовать как квалификатор r.Reader.File
. С именованными полями фокус не работает.type ReadCloser struct {
f *os.File //именованное поле f -имя *os.File -тип
Reader //внедренное поле Reader -тип имени нет
}
var Urls = make(map[string]struct{}) //самая компактная реализация множества.
func IsNew(url string) bool{
if _, ok:=Urls(path.Base(url)); ok{ //зачем вам весь url. Берите только базу, это компактней и исключит рерайты
return false
}else{
/*тривиальная реализация кэша
if PresentInDb(url){ //посмотреть в базе
if len(Urls)>Limit{ //подчистить кэш
for k,v:=range Urls{
delete(Urls, k)
break
}
}
Urls(path.Base(url))=struct{}{} //подновить кэш
return false
}else{
можно раскомментировать*/
Urls(path.Base(url))=struct{}{}
return true
}
}
conn, err := redis.DialURL(YourRedisUrl, yourOptions)
var ID int64
ID=redis.Int64(conn.Do("INCR", "IDcounter"))
или на стороне Go сервераID=atomic.AddInt64(&ID, 1)
_, err := conn.Do("HMSET", redis.Args{}.Add(ID).AddFlat(&NewPost)...)
Как будет представлен NewPost на стороне Go и на стороне redis вы не описали, поэтому предполагается struct и hash соответственно. ID реализован просто как redis key, а не поле записи, что упрощает индексирование и поиск. Замысел всех плясок с INCR (или sync.atomic.AddInt64() на стороне Go) в том что бы добиться безопасности и консистентности при конкурентном доступе многих goroutine. Если вы будете создавать посты только в одном потоке то ID++
вполне достаточно. Get never checks out or updates code stored in vendor directories.Нужно вручную или использовать вспомогательные приспособления. Их много, например https://glide.sh/