在执行结束时执行操作

I have an http server (launched using http.Handle) and I would like to do some operations.

How can I do that (on linux) ? Is it possible to do those operations in case of a ctrl-C ?

I'm not familiar with unix signals so the answer may be trivial.

You can subscribe to the TERM and INT signals using the signal package. But note that these signals are only sent when the process is killed explicitly; normal exit (initiated by the process itself) does not involve any sort of signals. I think for normal exit just do something in the main routine (which supposedly should spawn worker goroutines and then wait on them).

Read man 7 signal for more general info on POSIX signals.

Using kostix answer, I built this code (now adapted to Go1) to catch the interrupt signal and do some operations before exiting :

go func() {
    sigchan := make(chan os.Signal, 10)
    signal.Notify(sigchan, os.Interrupt)
    <-sigchan
    log.Println("Program killed !")

    // do last actions and wait for all write operations to end

    os.Exit(0)
}()

// start main program tasks

I suppose author is interested not only in Ctrl+C and offer more broad solution for Linux (for Windows signals see x/sys/windows):

package main

import (
  "os"
  "os/signal"
  "syscall"
  "fmt"
)

func getFireSignalsChannel() chan os.Signal {

  c := make(chan os.Signal, 1)
  signal.Notify(c,
    // https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html
    syscall.SIGTERM, // "the normal way to politely ask a program to terminate"
    syscall.SIGINT, // Ctrl+C
    syscall.SIGQUIT, // Ctrl-\
    syscall.SIGKILL, // "always fatal", "SIGKILL and SIGSTOP may not be caught by a program"
    syscall.SIGHUP, // "terminal is disconnected"
  )
  return c

}

func exit() {
  syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
}

func main() {

  exitChan := getFireSignalsChannel()
  input, err := os.Open("input.txt")
  if err != nil {
    panic(err)
  }
  defer input.Close()
  <-exitChan
  fmt.Println("Exiting!")
  return
  // All main deferreds executed here even in case of panic.
  // Non-main deferreds are not executed here.

}

P.S. None of signals handles os.Exit.

With this configuration on Ctrl+C or on receiving other signal program will push os.Signal into channel exitChan which will unblock <-exitChan operation and the main function will continue execution on the final lines, then return, then execute deferred functions.

Non-Main Deferreds

For non-main deferred you may:

  1. Use https://github.com/tebeka/atexit
  2. Move important resources into global array and release them in a main deferred. This solution is not perfect if you don't use transaction: 1) create resource, 2) add to array, -- which shouldn't be interrupted by exit. Also non-concurrent read-write access to a slice must be provided I guess.