code: func (locker *ConsulLocker) LockUpload(id string) error {
  	lock, err := locker.Client.LockOpts(&consul.LockOptions{
  		Key:          id + "/" + consul.DefaultSemaphoreKey,
  		LockTryOnce:  true,
  		LockWaitTime: time.Second,
  	})
  	if err != nil {
  		return err
  	}
  
  	ch, err := lock.Lock(nil)
  	if ch == nil {
  		if err == nil || err == consul.ErrLockHeld {
  			return tusd.ErrFileLocked
  		} else {
  			return err
  		}
  	}
  
  	locker.mutex.Lock()
  	defer locker.mutex.Unlock()
  	// Only add the lock to our list if the acquire was successful and no error appeared.
  	locker.locks[id] = lock
  
  	go func() {
  		// This channel will be closed once we lost the lock. This can either happen
  		// wanted (using the Unlock method) or by accident, e.g. if the connection
  		// to the Consul server is lost.
  		<-ch
  
  		locker.mutex.RLock()
  		defer locker.mutex.RUnlock()
  		// Only proceed if the lock has been lost by accident. If we cannot find it
  		// in the map, it has already been gracefully removed (see UnlockUpload).
  		if _, ok := locker.locks[id]; !ok {
  			return
  		}
  
  		msg := "consullocker: lock for upload '" + id + "' has been lost."
  		if locker.ConnectionName != "" {
  			msg += " Please ensure that the connection to '" + locker.ConnectionName + "' is stable."
  		} else {
  			msg += " Please ensure that the connection to Consul is stable (use ConnectionName to provide a printable name)."
  		}
  
  		// This will cause the program to crash since a panic can only be recovered
  		// from the causing goroutine.
  		panic(msg)
  	}()
  
  	return nil
  }
docs: // LockUpload tries to obtain the exclusive lock.