How to cross-compile Go programs for Windows, macOS, and Linux

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"
...

Compile for Windows

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

Compile for macOS

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

Compile for Linux

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

 

go luhn

проверка Луна

 



код луна

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),
	)
}

Golang mux gzip

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)
	}
}

Go and JSON

Parsing into a Struct

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”.

Rendering from a Struct

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

Golang тестирование http

Пример тестирование 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