This is unnecessarily complicated. The beautiful thing about Ed25519 keys (private and public) is that they are simply opaque byte strings. Indeed, here is Go's definition of ed25519.PublicKey:

  type PublicKey []byte
So if your application uses exclusively Ed25519, you can just pass around the raw bytes (encoded as base64 as desired). There is no need to muck around with ASN.1.

And if you do need to transmit keys in ASN.1 structures, Go's standard library has functions for that:

https://golang.org/pkg/crypto/x509/#MarshalPKIXPublicKey

https://golang.org/pkg/crypto/x509/#ParsePKIXPublicKey

The author has just written worse versions of those functions.

Came here to say this. Please don't use PKIX, ASN.1, and Base64-of-DER-without-PEM-headers for Ed25519. Those are all extra complexity from protocols that were misguidedly built with runtime agility, or from a different time in cryptography engineering in which we really felt the need to put dynamic types on everything. [0][1]

An Ed25519 public key is a 32 bytes sequence. An Ed25519 private key (called seed in crypto/ed25519 for unfortunate historical standardization reasons) is a 32 byte sequence. That's it.

Here they are encoded in Base64.

    public key: 5uW7anEGF1nIjGfp5pS2kiN0cn2mGYkuSa+TCBoFIbQ=
    private key: shhKyGTvTeLjXGDCjEQgHRA7ps3LRNNfoO5S714kinU=
age [2] similarly uses Curve25519 keys encoded with Bech32 to make them easier to copy-paste and read aloud. Look how nice they look compared to PKIX blobs!

    $ age-keygen
    # created: 2021-04-23T12:31:14-04:00
    # public key: age1gek0nrawzg9fhkrzcmt4ql7au0n6hwflz7lqqc8wwcvefn2vssgsa4uulp
    AGE-SECRET-KEY-19JFPFAY2DF3HJP5DFGVSY4A4G4YSRHG4ZCJMKNC5MFD9C9ZN5LCSG8VTDL 
I'll think about how to make the crypto/ed25519 godoc point people in the right direction once Go 1.17 enters feature freeze.

[0] https://www.imperialviolet.org/2016/05/16/agility.html

[1] https://buttondown.email/cryptography-dispatches/archive/cry...

[2] https://github.com/FiloSottile/age