SELECT * FROM schema_migrations;
+---------+-------+
| version | dirty |
+---------+-------+
| 1 | 1 |
+---------+-------+
1 row in set (0.00 sec)
migrate -path $PATH_TO_YOUR_MIGRATIONS -database $YOUR_DATABASE_URL force $VERSION
usersQuerySvc := usersservices.NewQuerySvc(usersRepo, ...)
usersSignupSvc := usersservices.NewSignupSvc(usersQuerySvc, usersCommandSvc)
// например сервис для админов (с проверкой полномочий), методы которого уже можно использовать в endpoint'ax
usersAdminSvc := usersservices.NewAdminSvc(usersQuerySvc, usersCommandSvc)
projectSvc := projectservices.New(usersQuerySvc)
func main() {
var mux = http.NewServeMux()
mux.HandleFunc("/", indexPage)
var serv = &http.Server{
// добавляете параметр
Handler: mux,
Addr: serverPort,
ReadTimeout: 15 * time.Second,
WriteTimeout: 15 * time.Second,
}
// вызываете с двумя параметрами
log.Fatal(serv.ListenAndServeTLS(TLScert, TLSkey))
}
package main
import (
"io"
"log"
"os"
"path/filepath"
)
type BlobReader struct {
keys []string
currentKey uint64
reader io.ReadCloser
}
func NewBlobReader(keys []string) *BlobReader {
return &BlobReader{
keys: keys,
}
}
// Read реализация интерфейса io.Reader, чтобы можно было ваш reader использовать в io.Copy
func (br *BlobReader) Read(p []byte) (int, error) {
var err error
// открываем каждый файл по очереди
if br.reader == nil {
filePath := filepath.Join(".", "blobs", br.keys[br.currentKey])
br.reader, err = os.Open(filePath)
if err != nil {
return 0, err
}
}
// читаем данные из текущего открытого файла, пока данные не закончатся
n, err := br.reader.Read(p)
// если данные в файле закончились, закрываем его
if err == io.EOF {
br.currentKey++
br.reader.Close()
br.reader = nil
// io.EOF в err должно вернуть только у последнего файла, чтобы io.Copy считал все файлы и не завис на последнем.
if br.currentKey < uint64(len(br.keys)) {
err = nil
}
}
return n, err
}
func main() {
blobReader := NewBlobReader([]string{
"2050-part1",
"2050-part2",
"2050-part3",
})
_, err := io.Copy(os.Stdout, blobReader)
if err != nil {
log.Fatalln(err)
}
log.Println("Done")
}
package main
import (
"context"
"fmt"
"sync"
)
func worker(ctx context.Context, worderID int, data chan int, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Printf("worker %d started\n", worderID)
for {
fmt.Printf("worker %d enter for\n", worderID)
select {
case <-ctx.Done():
fmt.Printf("worker %d cancelled\n", worderID)
return
case v, ok := <-data:
fmt.Printf("worker %d got data: %v, ok: %v\n", worderID, v, ok)
if !ok {
fmt.Printf("worker %d data channel was closed\n", worderID)
return
}
}
}
}
func main() {
var wg sync.WaitGroup
ctx, cancel := context.WithCancel(context.Background())
channels := make([]chan int, 10)
for i := 0; i < 10; i++ {
wg.Add(1)
channels[i] = make(chan int)
go worker(ctx, i, channels[i], &wg)
}
for i := 0; i < 10; i++ {
channels[i] <- i
}
cancel()
wg.Wait()
}
package main
import "fmt"
// объявляем интерфейс
type Profile interface {
GetFullName() string
}
// структура данных, которая будет реализовывать интерфейс Profile
type User struct {
Name string
LastName string
}
// реализация метода интерфейса Profile
func (u User) GetFullName() string {
return u.Name + ` ` + u.LastName
}
// пример функции, которая извлекает/формирует данные и возвращает слайс интерфейсов
func getProfiles() []Profile {
// создаём слайс интерфейсов
var result = make([]Profile, 10)
for i := 0; i<10; i++ {
// но заполняем слайс структурами, которые реализуют этот интерфейс
result[i] = User{
Name: fmt.Sprintf("Name%d", i),
LastName: fmt.Sprintf("LastName%d", i),
}
}
return result
}
// пример функции, которая работает со слайсом интерфейсов.
func printProfiles(profiles []Profile) {
for _, profile := range profiles {
fmt.Println(profile.GetFullName())
}
}
func main() {
printProfiles(getProfiles())
}
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)
func main() {
artist := "Madonna"
token := "5936fb55e90cdd9938f8e7086c783c40"
url := fmt.Sprintf(
"http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist=%s&api_key=%s&format=json", artist, token)
res, err := http.Get(url)
if err != nil {
log.Fatal(err)
}
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
var data map[string]interface{}
// десериализуете JSON
err = json.Unmarshal(body, &data)
if err != nil {
log.Fatal(err)
}
// сериализуете данные в JSON
marshaledDataBytes, err := json.MarshalIndent(data, "", "\t")
fmt.Println(string(marshaledDataBytes))
}
package main
import (
"log"
"time"
)
func doSomethingEvery5Seconds(ch chan bool) {
log.Println("Started!")
for {
select {
case <-ch:
return
default:
log.Println("I am doing this!")
time.Sleep(1 * time.Second)
}
}
}
func main() {
ch := make(chan bool, 1)
go doSomethingEvery5Seconds(ch)
time.Sleep(15 * time.Second)
close(ch) // Останавливаем спустя 15 секунд
}
[
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}
]
package main
import (
"database/sql"
"encoding/json"
"log"
"net/http"
_ "github.com/go-sql-driver/mysql"
)
type Post struct {
Userid int `json:"userId"`
ID int `json:"id"`
Title string `json:"title"`
Body string `json:"body"`
}
func main() {
posts, err := fetchPosts("https://jsonplaceholder.typicode.com/posts?id=1")
if err != nil {
log.Fatal(err)
}
db, err := sql.Open("mysql", "root:password@/Posts")
if err != nil {
log.Fatal(err)
}
err = savePosts(db, posts)
if err != nil {
log.Fatal(err)
}
}
func fetchPosts(url string) ([]Post, error) {
resp, err := http.Get(url)
if err != nil {
return nil, err
}
var posts []Post
err = json.NewDecoder(resp.Body).Decode(&posts)
return posts, err
}
func savePosts(db *sql.DB, posts []Post) error {
for _, post := range posts {
_, err := db.Exec("insert into post (id, user_id, title, body) values(?, ?, ?, ?)",
post.ID, post.Userid, post.Title, post.Body)
if err != nil {
return err
}
}
return nil
}
yourproject.com/main.go
yourproject.com/go.mod (появится после выполнения команды go mod init)
yourproject.com/pkg1/pkg1.go
package main
import "yourproject.com/pkg1"
func main() {
pkg1.SomeFunc()
}
package pkg1
import "fmt"
func SomeFunc() {
fmt.Println(`SomeFunc called`)
}
users/repo.go - описание интерфейса Repo
users/repo/repo.go - тут инициализация любого типа реализации в зависимости от конфига
users/repo/repo_test.go - тут тесты
(создаю все типы репозиториев (mongo, redis...)) и одними и теми же тестами прогоняю каждый тип.
Тут и инициализация репозиториев для тестов и зачистка после тестов.)
users/repo/mongodb - реализация (импортирует пакет users при необходимости)
users/repo/redis
users/repo/sqlite