code: func SignBytes(payload []byte, signingAlg string, key interface{}, options ...func(*JoseConfig)) (token string, err error) {
  	if signer, ok := jwsHashers[signingAlg]; ok {
  
  		cfg := &JoseConfig{CompressionAlg: "", Headers: make(map[string]interface{})}
  
  		//apply extra options
  		for _, option := range options {
  			option(cfg)
  		}
  
  		//make sure defaults and requires are managed by us
  		cfg.Headers["alg"] = signingAlg
  
  		paloadBytes := payload
  		var header []byte
  		var signature []byte
  
  		if header, err = json.Marshal(cfg.Headers); err == nil {
  			securedInput := []byte(compact.Serialize(header, paloadBytes))
  
  			if signature, err = signer.Sign(securedInput, key); err == nil {
  				return compact.Serialize(header, paloadBytes, signature), nil
  			}
  		}
  
  		return "", err
  	}
  
  	return "", errors.New(fmt.Sprintf("jwt.Sign(): unknown algorithm: '%v'", signingAlg))
  }
docs: // Sign produces signed JWT token given arbitrary binary payload, signature algorithm to use (see constants for list of supported algs), signing key and extra options (see option functions)
  // Signing key is of different type for different signing alg, see specific
  // signing alg implementation documentation.
  //
  // It returns 3 parts signed JWT token as string and not nil error if something went wrong.