kvlog/writer.go
func (w *logWriter) Write(p []byte) (n int, err error) {
	var (
		now     = time.Now() // do this early
		prefix  string
		logdate []byte
		logtime []byte
		file    []byte
		changed bool
	)

	if w.utc {
		now = now.UTC()
	}
	if w.prefixb != nil {
		if bytes.HasPrefix(p, w.prefixb) {
			prefix = w.prefixs
			p = p[len(prefix):]
		} else {
			changed = true
		}
	}
	p = bytes.TrimLeftFunc(p, isspace)
	if w.dateRE != nil {
		dateb := w.dateRE.Find(p)
		if dateb != nil {
			logdate = dateb
			p = p[len(dateb):]
			p = bytes.TrimLeftFunc(p, isspace)
		} else {
			changed = true
		}
	}
	if w.timeRE != nil {
		timeb := w.timeRE.Find(p)
		if timeb != nil {
			logtime = timeb
			p = p[len(timeb):]
			p = bytes.TrimLeftFunc(p, isspace)
		} else {
			changed = true
		}
	}
	if w.fileRE != nil {
		fileb := w.fileRE.Find(p)
		if fileb != nil {
			file = fileb
			p = p[len(fileb):]
			p = bytes.TrimLeftFunc(p, isspace)
			skip := colonRE.Find(p)
			p = p[len(skip):]
		} else {
			changed = true
		}
	}

	w.output.mutex.Lock()
	if w.output.levels == nil {
		// apply the default levels as late as possible,
		// which gives the calling program an opportunity
		// to change default levels at program initialization
		w.output.setLevels(Levels)
	}
	if !w.output.shouldSuppress(p) {
		level, effect, skip := w.output.getLevel(p)
		p = p[skip:]
		msg := parse.Bytes(p)
		ent := logEntry{
			Timestamp: now,
			Prefix:    prefix,
			Date:      logdate,
			Time:      logtime,
			File:      file,
			Level:     level,
			Effect:    effect,
			Text:      msg.Text,
			List:      msg.List,
		}
		w.output.handler(&ent)
		msg.Release()
	}
	w.output.mutex.Unlock()

	if changed && !w.changed {
		w.changed = true
		go func() {
			w.output.Attach(w.logger)
			if w.logger == nil {
				log.Println("warning: logger details changed after kvlog.Attach")
			} else {
				w.logger.Println("warning: logger details after kvlog.Writer.Attach")
			}
		}()
	}

	return len(p), nil
}
func (w *logWriter) Write(p []byte) (n int, err error) {
	var (
		now     = time.Now() // do this early
		prefix  string
		logdate []byte
		logtime []byte
		file    []byte
		changed bool
	)

	if w.utc {
		now = now.UTC()
	}
	if w.prefixb != nil {
		if bytes.HasPrefix(p, w.prefixb) {
			prefix = w.prefixs
			p = p[len(prefix):]
		} else {
			changed = true
		}
	}
	p = bytes.TrimLeftFunc(p, isspace)
	if w.dateRE != nil {
		dateb := w.dateRE.Find(p)
		if dateb != nil {
			logdate = dateb
			p = p[len(dateb):]
			p = bytes.TrimLeftFunc(p, isspace)
		} else {
			changed = true
		}
	}
	if w.timeRE != nil {
		timeb := w.timeRE.Find(p)
		if timeb != nil {
			logtime = timeb
			p = p[len(timeb):]
			p = bytes.TrimLeftFunc(p, isspace)
		} else {
			changed = true
		}
	}
	if w.fileRE != nil {
		fileb := w.fileRE.Find(p)
		if fileb != nil {
			file = fileb
			p = p[len(fileb):]
			p = bytes.TrimLeftFunc(p, isspace)
			skip := colonRE.Find(p)
			p = p[len(skip):]
		} else {
			changed = true
		}
	}

	w.output.mutex.Lock()
	if w.output.levels == nil {
		// apply the default levels as late as possible,
		// which gives the calling program an opportunity
		// to change default levels at program initialization
		w.output.setLevels(Levels)
	}
	if !w.output.shouldSuppress(p) {
		level, effect, skip := w.output.getLevel(p)
		p = p[skip:]
		msg := parse.Bytes(p)
		ent := logEntry{
			Timestamp: now,
			Prefix:    prefix,
			Date:      logdate,
			Time:      logtime,
			File:      file,
			Level:     level,
			Effect:    effect,
			Text:      msg.Text,
			List:      msg.List,
		}
		w.output.handler(&ent)
		msg.Release()
	}
	w.output.mutex.Unlock()

	if changed && !w.changed {
		w.changed = true
		go func() {
			w.output.Attach(w.logger)
			if w.logger == nil {
				log.Println("warning: logger details changed after kvlog.Attach")
			} else {
				w.logger.Println("warning: logger details after kvlog.Writer.Attach")
			}
		}()
	}

	return len(p), nil
}
// Write implements the io.Writer interface. This method is
// called from the logger. Because the logger's mutex is
// locked, and because we want to read the logger's prefix and
// its flags, we copy the details and let the actual logging
// be done by a goroutine.