Wrong error returned for CAS mismatch?

When cas mismatch error occurred, go sdk returns ErrKeyExists

That’s essentially correct - although it looks like the Go SDK is spelling it slightly incorrectly - it should be KeyEExists - from protocol_binary.h

        /** The key exists in the cluster (with another CAS value) */
        PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS = 0x02,

When insert new document with existed key, Go SDK returns ErrKeyExists too.
How do I distinguish this case with cas mismatch error?

You’d normally use a different opcode - use ADD (aka Insert) if you want to only create a document which doesn’t already exist, REPLACE if you only want to update an existing document. SET (aka Upset) will create or update.