func CreateHash(password string, params *Params) (hash string, err error) {
	salt, err := generateRandomBytes(params.SaltLength)
	if err != nil {
		return "", err
	}
	key := argon2.IDKey([]byte(password), salt, params.Iterations, params.Memory, params.Parallelism, params.KeyLength)
	b64Salt := base64.RawStdEncoding.EncodeToString(salt)
	b64Key := base64.RawStdEncoding.EncodeToString(key)
	hash = fmt.Sprintf("$argon2id$v=%d$m=%d,t=%d,p=%d$%s$%s", argon2.Version, params.Memory, params.Iterations, params.Parallelism, b64Salt, b64Key)
	return hash, nil
}
CreateHash returns a Argon2id hash of a plain-text password using the
provided algorithm parameters. The returned hash follows the format used by
the Argon2 reference C implementation and contains the base64-encoded Argon2id d
derived key prefixed by the salt and parameters. It looks like this:

$argon2id$v=19$m=65536,t=3,p=2$c29tZXNhbHQ$RdescudvJCsgt3ub+b+dWRWJTmaaJObG
package argon2id
import (
	"crypto/rand"
	"crypto/subtle"
	"encoding/base64"
	"errors"
	"fmt"
	"strings"
	"golang.org/x/crypto/argon2"
)
var (
	ErrInvalidHash = errors.New("argon2id: hash is not in the correct format")
	ErrIncompatibleVersion = errors.New("argon2id: incompatible version of argon2")
)
var DefaultParams = &Params{
	Memory:      64 * 1024,
	Iterations:  1,
	Parallelism: 2,
	SaltLength:  16,
	KeyLength:   32,
}
type Params struct {
	Memory uint32
	Iterations uint32
	Parallelism uint8
	SaltLength uint32
	KeyLength uint32
}