code: func (cc *clientConn) handshake(ctx context.Context) error {
  	if err := cc.writeInitialHandshake(); err != nil {
  		return err
  	}
  	if err := cc.readOptionalSSLRequestAndHandshakeResponse(ctx); err != nil {
  		err1 := cc.writeError(err)
  		if err1 != nil {
  			logutil.Logger(ctx).Debug("writeError failed", zap.Error(err1))
  		}
  		return err
  	}
  	data := cc.alloc.AllocWithLen(4, 32)
  	data = append(data, mysql.OKHeader)
  	data = append(data, 0, 0)
  	if cc.capability&mysql.ClientProtocol41 > 0 {
  		data = dumpUint16(data, mysql.ServerStatusAutocommit)
  		data = append(data, 0, 0)
  	}
  
  	err := cc.writePacket(data)
  	cc.pkt.sequence = 0
  	if err != nil {
  		return err
  	}
  
  	return cc.flush()
  }
docs: // handshake works like TCP handshake, but in a higher level, it first writes initial packet to client,
  // during handshake, client and server negotiate compatible features and do authentication.
  // After handshake, client can send sql query to server.