GoDoc Tricks: https://pkg.go.dev/github.com/fluhus/godoc-tricks
https://chrome.google.com/webstore/detail/go-search-extension/epanejkfcekejmmfbcpbcbigfpefbnlb
go mod init github.com/coolaj86/projectname
mkdir -p tools
go get github.com/goware/modvendor
go get github.com/kyleconroy/sqlc/cmd/sqlc@latest
go mod vendor
go run -mod=vendor github.com/goware/modvendor -copy="**/*.c **/*.h **/*.proto" -v
build.go
//go:generate go run -mod=vendor github.com/kyleconroy/sqlc/cmd/sqlc generate
package main
tools/tools.go
:
//go:build tools
package tools
import (
// for the modvendor command
_ "github.com/goware/modvendor"
// for the sqlc command
_ "github.com/kyleconroy/sqlc/cmd/sqlc"
)
go mod tidy
go generate -mod=vendor ./...
module github.com/example/project
require (
github.com/SermoDigital/jose v0.0.0-20180104203859-803625baeddc
github.com/google/uuid v1.1.0
)
exclude github.com/SermoDigital/jose v0.9.1
replace github.com/google/uuid v1.1.0 => git.coolaj86.com/coolaj86/uuid.go v1.1.1
See https://stackoverflow.com/a/53824026/151312.
sort.Strings(haystack)
func contains(haystack []string, needle string) bool {
i := sort.SearchStrings(haystack, needle)
return i < len(haystack) && needle == haystack[i]
}
https://phrase.com/blog/posts/internationalization-i18n-go/
In part from https://blog.cloudflare.com/the-complete-guide-to-golang-net-http-timeouts/
c := &http.Client{
Transport: &http.Transport{
Dial: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).Dial,
TLSHandshakeTimeout: 10 * time.Second,
ResponseHeaderTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
}
c := make(chan struct{})
timer := time.AfterFunc(5*time.Second, func() {
close(c)
})
// Serve 256 bytes every second.
req, err := http.NewRequest("GET", "http://httpbin.org/range/2048?duration=8&chunk_size=256", nil)
if err != nil {
log.Fatal(err)
}
req.Cancel = c
log.Println("Sending request...")
resp, err := c.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
s := base64.RawURLEncoding.EncodeToString([]byte(data))
b, err := base64.RawURLEncoding.DecodeString(s)
var Rando = rand.Reader
b := make([]byte, 16)
n, err := Rando.Read(b)
id := base64.RawURLEncoding.EncodeToString(b)
func ParseSeconds(s string) (int64, int64, error) {
seconds, err := strconv.ParseFloat(s, 64)
if nil != err {
return 0.0, 0.0, err
}
secs, nanos := SecondsToInts(seconds)
return secs, nanos, nil
}
func SecondsToInts(seconds float64) (int64, int64) {
secs := math.Floor(seconds)
nanos := math.Round((seconds - secs) * 1_000_000_000)
return int64(secs), int64(nanos)
}
func ParseSeconds(secs string) (int64, int64, error) {
// "789.0123" => []string{"789", "0123"}
parts := strings.Split(secs, ".")
if len(parts) > 2 {
return 0, 0, errors.New("could not parse as seconds")
} else if len(parts) < 2 {
// no nanoseconds, just seconds
// "789" => []string{"789"}
s, err := strconv.ParseInt(parts[0], 10, 64)
return s, 0, err
}
// convert the second's part
s, err := strconv.ParseInt(parts[0], 10, 64)
if nil != err {
return 0, 0, err
}
// get nanoseconds from fractional second
d, err := time.ParseDuration("0." + parts[1] + "s")
return s, d.Nanoseconds(), err
}
func ParseUnixTime(seconds string) (time.Time, error) {
secs, nano, err := ParseSeconds(seconds)
if nil != err {
return time.Time{}, err
}
return time.Unix(secs, nano), nil
}
func ToUnixSeconds(t time.Time) float64 {
// 1614236182.651912345
secs := float64(t.Unix()) // 1614236182
nanos := float64(t.Nanosecond()) / 1_000_000_000.0 // 0.651912345
// in my case I want to truncate the precision to milliseconds
nanos = math.Round((10000 * nanos) / 10000) // 0.6519
s := secs + nanos // 1614236182.651912345
return s
}
// Left pad up to 10 spaces
fmt.Sprintf("'%*s'", 10, "Hello")
// ' Hello'
// Right pad up to 10 spaces
fmt.Sprintf("'Hello%-*s'", 10, "Hello")
// 'Hello '
// Left pad up to 10 zeros
fmt.Sprintf("'%0*s'\n", 10, "Hello")
// '00000Hello'
// Right pad up to 10 zeros... psych!
fmt.Sprintf("'%-0*s'\n", 10, "Hello")
// 'Hello '
func SafeRequest(req *http.Request) (*http.Response, error) {
var netTransport = &http.Transport{
Dial: (&net.Dialer{
Timeout: 5 * time.Second,
}).Dial,
TLSHandshakeTimeout: 5 * time.Second,
}
var netClient = &http.Client{
Timeout: time.Second * 10,
Transport: netTransport,
}
response, err := netClient.Do(req)
if nil != err {
return nil, err
}
body := response.Body
response.Body = io.LimitReader(body, 1024 * 1024)
//response.Body = MaxBytesReader(body, 1024*1024)
return response, nil
}
srv := &http.Server{
Addr: runOpts.Addr,
Handler: r,
ReadHeaderTimeout: 2 * time.Second,
ReadTimeout: 10 * time.Second,
WriteTimeout: 20 * time.Second,
MaxHeaderBytes: 1024 * 1024, // 1MiB
}
if err := srv.ListenAndServe(); nil != err {
fmt.Fprintf(os.Stderr, "%s", err)
os.Exit(1)
return
}
var srv *httptest.Server
func TestMain(m *testing.M) {
// math/rand.Seed(0)
srv = httptest.NewServer(mux)
os.Exit(m.Run())
}
client := srv.Client()
urlstr, _ := url.Parse(srv.URL + "/debug/verify?exp=false")
req := &http.Request{
Method: "POST",
URL: urlstr,
//Body: ioutil.NopCloser(bytes.NewReader(jws)),
Header: http.Header{},
}
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", jwt))
res, err := client.Do(req)
if nil != err {
t.Error(err)
return
}
data, err := ioutil.ReadAll(res.Body)
if nil != err {
t.Error(err)
return
}
if 200 != res.StatusCode {
log.Printf(string(data))
t.Error(fmt.Errorf("bad status code: %d", res.StatusCode))
return
}
r.Body = http.MaxBytesReader(w, r.Body, 1 << 20)
TODO
import "crypto/subtle"
func ConstantTimeCompare(x, y []byte) bool {
return 1 == subtle.ConstantTimeCompare(x, y)
}
-
go clean -testcache
https://numidian.io/convert/json/to/postgres
export GO111MODULE=on
export GOPROXY=direct
export GOSUMDB=off
const (
// sha1Prefix is the prefix used by GitHub before the HMAC hexdigest.
sha1Prefix = "sha1"
// sha256Prefix and sha512Prefix are provided for future compatibility.
sha256Prefix = "sha256"
sha512Prefix = "sha512"
// signatureHeader is the GitHub header key used to pass the HMAC hexdigest.
signatureHeader = "X-Hub-Signature"
)
if len(secretToken) > 0 {
sig := r.Header.Get(signatureHeader)
if err := ValidateSignature(sig, body, secretToken); err != nil {
return nil, err
}
}
// ValidateSignature validates the signature for the given payload.
// signature is the GitHub hash signature delivered in the X-Hub-Signature header.
// payload is the JSON payload sent by GitHub Webhooks.
// secretToken is the GitHub Webhook secret token.
//
// GitHub API docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github
func ValidateSignature(signature string, payload, secretToken []byte) error {
messageMAC, hashFunc, err := messageMAC(signature)
if err != nil {
return err
}
if !checkMAC(payload, messageMAC, secretToken, hashFunc) {
return errors.New("payload signature check failed")
}
return nil
}
// checkMAC reports whether messageMAC is a valid HMAC tag for message.
func checkMAC(message, messageMAC, key []byte, hashFunc func() hash.Hash) bool {
expectedMAC := genMAC(message, key, hashFunc)
return hmac.Equal(messageMAC, expectedMAC)
}
// messageMAC returns the hex-decoded HMAC tag from the signature and its
// corresponding hash function.
func messageMAC(signature string) ([]byte, func() hash.Hash, error) {
if signature == "" {
return nil, nil, errors.New("missing signature")
}
sigParts := strings.SplitN(signature, "=", 2)
if len(sigParts) != 2 {
return nil, nil, fmt.Errorf("error parsing signature %q", signature)
}
var hashFunc func() hash.Hash
switch sigParts[0] {
case sha1Prefix:
hashFunc = sha1.New
case sha256Prefix:
hashFunc = sha256.New
case sha512Prefix:
hashFunc = sha512.New
default:
return nil, nil, fmt.Errorf("unknown hash type prefix: %q", sigParts[0])
}
buf, err := hex.DecodeString(sigParts[1])
if err != nil {
return nil, nil, fmt.Errorf("error decoding signature %q: %v", signature, err)
}
return buf, hashFunc, nil
}
Build Tag Syntax | Build Tag Sample | Boolean Statement |
---|---|---|
Space-separated elements | // +build pro enterprise | pro OR enterprise |
Comma-separated elements | // +build pro,enterprise | pro AND enterprise |
Exclamation point elements | // +build !pro | NOT pro |