The standard library packages exist in the first group.
Then Third — party libs.
At the end of the Imports from your project.
The standard library packages exist in the first group.
Then Third — party libs.
At the end of the Imports from your project.
You can use the go env
command to view the values of these variables on your machine:
$ go env
...
GOARCH="amd64"
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
...
Here’s the command you need to run to compile your Go project for a 64-bit Windows machine:
$ GOOS=windows GOARCH=amd64 go build -o bin/app-amd64.exe app.go
In this scenario, GOOS
is windows, and GOARCH
is amd64
indicating a 64-bit architecture. If you need to support a 32-bit architecture, all you need to do is change GOARCH
to 386
.
$ GOOS=windows GOARCH=386 go build -o bin/app-386.exe app.go
The GOARCH
values for Windows are also valid for macOS, but in this case the required GOOS
value is darwin
:
# 64-bit
$ GOOS=darwin GOARCH=amd64 go build -o bin/app-amd64-darwin app.go
# 32-bit
$ GOOS=darwin GOARCH=386 go build -o bin/app-386-darwin app.go
To build your Go program for Linux, use linux
as the value of GOOS
and the appropriate GOARCH
value for your target CPU architecture:
# 64-bit
$ GOOS=linux GOARCH=amd64 go build -o bin/app-amd64-linux app.go
# 32-bit
$ GOOS=linux GOARCH=386 go build -o bin/app-386-linux app.go
Install all Go project dependencies in one command
go get ./...
downloads all the dependencies
go get -u -v -f all
проверка Луна
код луна
https://go.dev/play/p/S_nrTTrk0Wq
package main
import (
"fmt"
"github.com/theplant/luhn"
)
func main() {
fmt.Println(
luhn.Valid(6174570601580),
luhn.Valid(422466257468622),
luhn.Valid(2352238521358),
luhn.Valid(7162683784855),
)
}
Using JWT for Authentication in a Golang Application
https://developer.vonage.com/blog/2020/03/13/using-jwt-for-authentication-in-a-golang-application-dr
https://disk.yandex.ru/d/IzZ3Y6P_EAAC6w
https://github.com/victorsteven/jwt-best-practices
package mux import ( "compress/gzip" "fmt" "log" "mime" "net/http" "path/filepath" "strings" ) func GzipAutoMiddleware(hf http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { accept := r.Header.Get("Accept-Encoding") content := r.Header.Get("Content-Encoding") if strings.Contains(content, "gzip") { reader, e := gzip.NewReader(r.Body) if e != nil { e = fmt.Errorf("reading gzip body failed:%w", e) log.Println(e) http.Error(w, e.Error(), http.StatusBadRequest) return } r.Body = reader } if strings.Contains(accept, "gzip") { ext := filepath.Ext(r.RequestURI) mime := mime.TypeByExtension(ext) if r.RequestURI == "/" || strings.HasPrefix(mime, "text/") || ext == ".json" || ext == ".js" { w.Header().Set("Content-Encoding", "gzip") gw := gzip.NewWriter(w) defer gw.Flush() defer gw.Close() w = &ResponseWriterBuf{ Rw: w, Writer: gw, } } } hf(w, r) } }
Here’s an example of parsing into a struct:
type App struct { Id string `json:"id"` Title string `json:"title"` } data := []byte(` { "id": "k34rAT4", "title": "My Awesome App" } `) var app App err := json.Unmarshal(data, &app)
What you’re left with is app
populated with the parsed JSON that was in data
. You’ll also notice that the go term for parsing json is “Unmarshalling”.
Outputting from a struct works exactly as parsing but in reverse:
data, err := json.Marshal(app)
As with all structs in Go, it’s important to remember that only fields with a capital first letter are visible to external programs like the JSON Marshaller.
You can get rid of the JsonType
as well and just use a slice:
package main
import (
"encoding/json"
"log"
)
func main() {
dataJson := `["1","2","3"]`
var arr []string
_ = json.Unmarshal([]byte(dataJson), &arr)
log.Printf("Unmarshaled: %v", arr)
}
// prints out:
// 2009/11/10 23:00:00 Unmarshaled: [1 2 3]
Code on play: https://play.golang.org/p/GNWlylavam
Пример тестирование API HTTP
package apiserver import ( "bytes" "encoding/json" "fmt" "github.com/stretchr/testify/assert" "net/http" "net/http/httptest" "rest_api/internal/app/model" "rest_api/internal/app/store/teststore" "testing" ) func TestServer_HandleCreateUser(t *testing.T) { s := newServer(teststore.New()) testCases := []struct { name string payload interface{} expectedCode int }{ { name: "valid", payload: map[string]interface{}{ "name": "Name", "email": "current@mail.com", "password": "123456", }, expectedCode: http.StatusCreated, }, { name: "empty payload", payload: "invalid", expectedCode: http.StatusBadRequest, }, { name: "invalid email", payload: map[string]interface{}{ "name": "Name", "email": "nenormalmail", "password": "12345", }, expectedCode: http.StatusUnprocessableEntity, }, { name: "invalid password", payload: map[string]interface{}{ "name": "Name", "email": "normal@mail.com", "password":"12345", }, expectedCode: http.StatusUnprocessableEntity, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { b := &bytes.Buffer{} json.NewEncoder(b).Encode(tc.payload) rec := httptest.NewRecorder() req, _ := http.NewRequest(http.MethodPost, "/create", b) s.ServeHTTP(rec, req) assert.Equal(t, tc.expectedCode, rec.Code) }) } } func TestServer_HandleAuthorizeUser(t *testing.T) { s := newServer(teststore.New()) testCases := []struct{ name string payload interface{} expectedCode int }{ { name: "valid", payload: map[string]interface{}{ "email": "test@example.com", "password": "password", }, expectedCode: http.StatusOK, }, { name: "invalid payload", payload: "invalid", expectedCode: http.StatusBadRequest, }, { name: "invalid user", payload: map[string]interface{}{ "email": "test@example.com", "password": "", }, expectedCode: http.StatusForbidden, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { user := map[string]interface{}{ "name": "User", "email": "test@example.com", "password": "password", } resp := struct { Token string `json:"token"` }{} b := &bytes.Buffer{} json.NewEncoder(b).Encode(user) rec := httptest.NewRecorder() req, _ := http.NewRequest(http.MethodPost, "/create", b) s.ServeHTTP(rec, req) json.NewEncoder(b).Encode(tc.payload) rec = httptest.NewRecorder() req, _ = http.NewRequest(http.MethodPost, "/authorize", b) s.ServeHTTP(rec, req) json.NewDecoder(rec.Body).Decode(resp) recToken := resp.Token assert.Equal(t, tc.expectedCode, rec.Code) assert.NotNil(t, recToken) }) } } func TestServer_HandleCreateArticle(t *testing.T) { s := newServer(teststore.New()) testCases := []struct{ name string payload interface{} expectedCode int }{ { name: "valid", payload: map[string]interface{}{ "article_header": "Test Article", "article_text": "Article test text", "author_id": 1, }, expectedCode: http.StatusCreated, }, { name: "invalid", payload: "invalid", expectedCode: http.StatusBadRequest, }, { name: "invalid article text", payload: map[string]interface{}{ "article_header": "Test Article", "article_text": 7, "author_id": 1, }, expectedCode: http.StatusBadRequest, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { us := map[string]interface{}{ "name": "User", "email": "user@mail.com", "password": "123456", } resp := &struct { User *model.User `json:"user"` Token string `json:"token"` }{} b := &bytes.Buffer{} json.NewEncoder(b).Encode(us) rec := httptest.NewRecorder() req, _ := http.NewRequest(http.MethodPost, "/create", b) s.ServeHTTP(rec, req) json.NewDecoder(rec.Body).Decode(resp) token := fmt.Sprintf("Baerer %s", resp.Token) json.NewEncoder(b).Encode(tc.payload) req, _ = http.NewRequest(http.MethodPost, "/private/create/article", b) rec = httptest.NewRecorder() req.Header.Add("Authorization", token) s.ServeHTTP(rec, req) assert.Equal(t, tc.expectedCode, rec.Code) }) } } func TestServer_HandleFindArticleByHeading(t *testing.T) { ts := teststore.New() ts.Article().CreateArticle(model.TestArticle(t, 5)) s := newServer(ts) testCases := []struct{ name string payload interface{} expectedCode int }{ { name: "valid", payload: map[string]interface{}{ "article_heading": "TestArticle", }, expectedCode: http.StatusOK, }, { name: "invalid article header", payload: map[string]interface{}{ "article_heading": "Article", }, expectedCode: http.StatusUnprocessableEntity, }, { name: "invalid request", payload: map[string]interface{}{ "article_heading": 1, }, expectedCode: http.StatusBadRequest, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { b := &bytes.Buffer{} json.NewEncoder(b).Encode(tc.payload) rec := httptest.NewRecorder() req, _ := http.NewRequest(http.MethodGet, "/find/article", b) s.ServeHTTP(rec, req) assert.Equal(t, tc.expectedCode, rec.Code) }) } } func TestServer_HandleChangeArticle(t *testing.T) { ts := teststore.New() article := model.TestArticle(t, 5) ts.Article().CreateArticle(article) s := newServer(ts) testCases := []struct{ name string payload interface{} expectedCode int }{ { name: "valid", payload: map[string]interface{}{ "id" : article.ID, "article_header": "Updated TestArticle", "article_text": "updated article text", }, expectedCode: http.StatusOK, }, { name: "invalid", payload: "invalid", expectedCode: http.StatusBadRequest, }, { name: "invalid id", payload: map[string]interface{}{ "id" : 1, "article_header": "Updated TestArticle", "article_text": "updated article text", }, expectedCode: http.StatusUnprocessableEntity, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { us := map[string]interface{}{ "name": "User", "email": "user@mail.com", "password": "123456", } resp := &struct { User *model.User `json:"user"` Token string `json:"token"` }{} b := &bytes.Buffer{} json.NewEncoder(b).Encode(us) rec := httptest.NewRecorder() req, _ := http.NewRequest(http.MethodPost, "/create", b) s.ServeHTTP(rec, req) json.NewDecoder(rec.Body).Decode(resp) token := fmt.Sprintf("Baerer %s", resp.Token) json.NewEncoder(b).Encode(tc.payload) req, _ = http.NewRequest(http.MethodPut, "/private/change/article", b) rec = httptest.NewRecorder() req.Header.Add("Authorization", token) s.ServeHTTP(rec, req) assert.Equal(t, tc.expectedCode, rec.Code) }) } } func TestServer_HandleDeleteArticle(t *testing.T) { ts := teststore.New() article := model.TestArticle(t, 5) ts.Article().CreateArticle(article) s := newServer(ts) testCases := []struct{ name string payload interface{} expectedCode int }{ { name: "valid", payload: map[string]interface{}{ "id" : article.ID, }, expectedCode: http.StatusOK, }, { name: "invalid", payload: "invalid", expectedCode: http.StatusBadRequest, }, { name: "invalid id", payload: map[string]interface{}{ "id" : 1, }, expectedCode: http.StatusUnprocessableEntity, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { us := map[string]interface{}{ "name": "User", "email": "user@mail.com", "password": "123456", } resp := &struct { User *model.User `json:"user"` Token string `json:"token"` }{} b := &bytes.Buffer{} json.NewEncoder(b).Encode(us) rec := httptest.NewRecorder() req, _ := http.NewRequest(http.MethodPost, "/create", b) s.ServeHTTP(rec, req) json.NewDecoder(rec.Body).Decode(resp) token := fmt.Sprintf("Baerer %s", resp.Token) json.NewEncoder(b).Encode(tc.payload) req, _ = http.NewRequest(http.MethodDelete, "/private/delete/article", b) rec = httptest.NewRecorder() req.Header.Add("Authorization", token) s.ServeHTTP(rec, req) assert.Equal(t, tc.expectedCode, rec.Code) }) } }
https://github.com/backspacesh/notebook_api/blob/5bdd97a7b98f85a84d6af4bb51da9d128a520384/internal/app/apiserver/server_internal_test.go