Web server using syscalls in Go












0












$begingroup$


I'm new to Go and wanted to implement a web server using system calls to get a better feel for how everything works.



I'm looking for feedback on idiomatic go especially error handling and using pointers.



I'm not particularly concerned about the completeness of the code. The primary goal was to learn syscalls in go.



package main

// Simple, single-threaded server using system calls instead of the net library.
//
// Omitted features from the go net package:
//
// - TLS
// - Most error checking
// - Only supports bodies that close, no persistent or chunked connections
// - Redirects
// - Deadlines and cancellation
// - Non-blocking sockets

import (
"bufio"
"errors"
"flag"
"io"
"log"
"net"
"net/textproto"
"os"
"strconv"
"strings"
"syscall"
)

// netSocket is a file descriptor for a system socket.
type netSocket struct {
// System file descriptor.
fd int
}

func (ns netSocket) Read(p byte) (int, error) {
if len(p) == 0 {
return 0, nil
}
n, err := syscall.Read(ns.fd, p)
if err != nil {
n = 0
}
return n, err
}

func (ns netSocket) Write(p byte) (int, error) {
n, err := syscall.Write(ns.fd, p)
if err != nil {
n = 0
}
return n, err
}

// Creates a new netSocket for the next pending connection request.
func (ns *netSocket) Accept() (*netSocket, error) {
// syscall.ForkLock doc states lock not needed for blocking accept.
nfd, _, err := syscall.Accept(ns.fd)
if err == nil {
syscall.CloseOnExec(nfd)
}
if err != nil {
return nil, err
}
return &netSocket{nfd}, nil
}

func (ns *netSocket) Close() error {
return syscall.Close(ns.fd)
}

// Creates a new socket file descriptor, binds it and listens on it.
func newNetSocket(ip net.IP, port int) (*netSocket, error) {
// ForkLock docs state that socket syscall requires the lock.
syscall.ForkLock.Lock()
// AF_INET = Address Family for IPv4
// SOCK_STREAM = virtual circuit service
// 0: the protocol for SOCK_STREAM, there's only 1.
fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0)
if err != nil {
return nil, os.NewSyscallError("socket", err)
}
syscall.ForkLock.Unlock()

// Allow reuse of recently-used addresses.
if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil {
syscall.Close(fd)
return nil, os.NewSyscallError("setsockopt", err)
}

// Bind the socket to a port
sa := &syscall.SockaddrInet4{Port: port}
copy(sa.Addr[:], ip)
if err = syscall.Bind(fd, sa); err != nil {
return nil, os.NewSyscallError("bind", err)
}

// Listen for incoming connections.
if err = syscall.Listen(fd, syscall.SOMAXCONN); err != nil {
return nil, os.NewSyscallError("listen", err)
}

return &netSocket{fd: fd}, nil
}

type request struct {
method string // GET, POST, etc.
header textproto.MIMEHeader
body byte
uri string // The raw URI from the request
proto string // "HTTP/1.1"
}

func parseRequest(c *netSocket) (*request, error) {
b := bufio.NewReader(*c)
tp := textproto.NewReader(b)
req := new(request)

// First line: parse "GET /index.html HTTP/1.0"
var s string
s, _ = tp.ReadLine()
sp := strings.Split(s, " ")
req.method, req.uri, req.proto = sp[0], sp[1], sp[2]

// Parse headers
mimeHeader, _ := tp.ReadMIMEHeader()
req.header = mimeHeader

// Parse body
if req.method == "GET" || req.method == "HEAD" {
return req, nil
}
if len(req.header["Content-Length"]) == 0 {
return nil, errors.New("no content length")
}
length, err := strconv.Atoi(req.header["Content-Length"][0])
if err != nil {
return nil, err
}
body := make(byte, length)
if _, err = io.ReadFull(b, body); err != nil {
return nil, err
}
req.body = body
return req, nil
}

func main() {
ipFlag := flag.String("ip_addr", "127.0.0.1", "The IP address to use")
portFlag := flag.Int("port", 8080, "The port to use.")
flag.Parse()

ip := net.ParseIP(*ipFlag)
port := *portFlag
socket, err := newNetSocket(ip, port)
defer socket.Close()
if err != nil {
panic(err)
}

log.Print("===============")
log.Print("Server Started!")
log.Print("===============")
log.Print()
log.Printf("addr: http://%s:%d", ip, port)

for {
// Block until incoming connection
rw, e := socket.Accept()
log.Print()
log.Print()
log.Printf("Incoming connection")
if e != nil {
panic(e)
}

// Read request
log.Print("Reading request")
req, err := parseRequest(rw)
log.Print("request: ", req)
if err != nil {
panic(err)
}

// Write response
log.Print("Writing response")
io.WriteString(rw, "HTTP/1.1 200 OKrn"+
"Content-Type: text/html; charset=utf-8rn"+
"Content-Length: 20rn"+
"rn"+
"<h1>hello world</h1>")
if err != nil {
log.Print(err.Error())
continue
}
}
}








share







New contributor




Joe is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$

















    0












    $begingroup$


    I'm new to Go and wanted to implement a web server using system calls to get a better feel for how everything works.



    I'm looking for feedback on idiomatic go especially error handling and using pointers.



    I'm not particularly concerned about the completeness of the code. The primary goal was to learn syscalls in go.



    package main

    // Simple, single-threaded server using system calls instead of the net library.
    //
    // Omitted features from the go net package:
    //
    // - TLS
    // - Most error checking
    // - Only supports bodies that close, no persistent or chunked connections
    // - Redirects
    // - Deadlines and cancellation
    // - Non-blocking sockets

    import (
    "bufio"
    "errors"
    "flag"
    "io"
    "log"
    "net"
    "net/textproto"
    "os"
    "strconv"
    "strings"
    "syscall"
    )

    // netSocket is a file descriptor for a system socket.
    type netSocket struct {
    // System file descriptor.
    fd int
    }

    func (ns netSocket) Read(p byte) (int, error) {
    if len(p) == 0 {
    return 0, nil
    }
    n, err := syscall.Read(ns.fd, p)
    if err != nil {
    n = 0
    }
    return n, err
    }

    func (ns netSocket) Write(p byte) (int, error) {
    n, err := syscall.Write(ns.fd, p)
    if err != nil {
    n = 0
    }
    return n, err
    }

    // Creates a new netSocket for the next pending connection request.
    func (ns *netSocket) Accept() (*netSocket, error) {
    // syscall.ForkLock doc states lock not needed for blocking accept.
    nfd, _, err := syscall.Accept(ns.fd)
    if err == nil {
    syscall.CloseOnExec(nfd)
    }
    if err != nil {
    return nil, err
    }
    return &netSocket{nfd}, nil
    }

    func (ns *netSocket) Close() error {
    return syscall.Close(ns.fd)
    }

    // Creates a new socket file descriptor, binds it and listens on it.
    func newNetSocket(ip net.IP, port int) (*netSocket, error) {
    // ForkLock docs state that socket syscall requires the lock.
    syscall.ForkLock.Lock()
    // AF_INET = Address Family for IPv4
    // SOCK_STREAM = virtual circuit service
    // 0: the protocol for SOCK_STREAM, there's only 1.
    fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0)
    if err != nil {
    return nil, os.NewSyscallError("socket", err)
    }
    syscall.ForkLock.Unlock()

    // Allow reuse of recently-used addresses.
    if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil {
    syscall.Close(fd)
    return nil, os.NewSyscallError("setsockopt", err)
    }

    // Bind the socket to a port
    sa := &syscall.SockaddrInet4{Port: port}
    copy(sa.Addr[:], ip)
    if err = syscall.Bind(fd, sa); err != nil {
    return nil, os.NewSyscallError("bind", err)
    }

    // Listen for incoming connections.
    if err = syscall.Listen(fd, syscall.SOMAXCONN); err != nil {
    return nil, os.NewSyscallError("listen", err)
    }

    return &netSocket{fd: fd}, nil
    }

    type request struct {
    method string // GET, POST, etc.
    header textproto.MIMEHeader
    body byte
    uri string // The raw URI from the request
    proto string // "HTTP/1.1"
    }

    func parseRequest(c *netSocket) (*request, error) {
    b := bufio.NewReader(*c)
    tp := textproto.NewReader(b)
    req := new(request)

    // First line: parse "GET /index.html HTTP/1.0"
    var s string
    s, _ = tp.ReadLine()
    sp := strings.Split(s, " ")
    req.method, req.uri, req.proto = sp[0], sp[1], sp[2]

    // Parse headers
    mimeHeader, _ := tp.ReadMIMEHeader()
    req.header = mimeHeader

    // Parse body
    if req.method == "GET" || req.method == "HEAD" {
    return req, nil
    }
    if len(req.header["Content-Length"]) == 0 {
    return nil, errors.New("no content length")
    }
    length, err := strconv.Atoi(req.header["Content-Length"][0])
    if err != nil {
    return nil, err
    }
    body := make(byte, length)
    if _, err = io.ReadFull(b, body); err != nil {
    return nil, err
    }
    req.body = body
    return req, nil
    }

    func main() {
    ipFlag := flag.String("ip_addr", "127.0.0.1", "The IP address to use")
    portFlag := flag.Int("port", 8080, "The port to use.")
    flag.Parse()

    ip := net.ParseIP(*ipFlag)
    port := *portFlag
    socket, err := newNetSocket(ip, port)
    defer socket.Close()
    if err != nil {
    panic(err)
    }

    log.Print("===============")
    log.Print("Server Started!")
    log.Print("===============")
    log.Print()
    log.Printf("addr: http://%s:%d", ip, port)

    for {
    // Block until incoming connection
    rw, e := socket.Accept()
    log.Print()
    log.Print()
    log.Printf("Incoming connection")
    if e != nil {
    panic(e)
    }

    // Read request
    log.Print("Reading request")
    req, err := parseRequest(rw)
    log.Print("request: ", req)
    if err != nil {
    panic(err)
    }

    // Write response
    log.Print("Writing response")
    io.WriteString(rw, "HTTP/1.1 200 OKrn"+
    "Content-Type: text/html; charset=utf-8rn"+
    "Content-Length: 20rn"+
    "rn"+
    "<h1>hello world</h1>")
    if err != nil {
    log.Print(err.Error())
    continue
    }
    }
    }








    share







    New contributor




    Joe is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.







    $endgroup$















      0












      0








      0





      $begingroup$


      I'm new to Go and wanted to implement a web server using system calls to get a better feel for how everything works.



      I'm looking for feedback on idiomatic go especially error handling and using pointers.



      I'm not particularly concerned about the completeness of the code. The primary goal was to learn syscalls in go.



      package main

      // Simple, single-threaded server using system calls instead of the net library.
      //
      // Omitted features from the go net package:
      //
      // - TLS
      // - Most error checking
      // - Only supports bodies that close, no persistent or chunked connections
      // - Redirects
      // - Deadlines and cancellation
      // - Non-blocking sockets

      import (
      "bufio"
      "errors"
      "flag"
      "io"
      "log"
      "net"
      "net/textproto"
      "os"
      "strconv"
      "strings"
      "syscall"
      )

      // netSocket is a file descriptor for a system socket.
      type netSocket struct {
      // System file descriptor.
      fd int
      }

      func (ns netSocket) Read(p byte) (int, error) {
      if len(p) == 0 {
      return 0, nil
      }
      n, err := syscall.Read(ns.fd, p)
      if err != nil {
      n = 0
      }
      return n, err
      }

      func (ns netSocket) Write(p byte) (int, error) {
      n, err := syscall.Write(ns.fd, p)
      if err != nil {
      n = 0
      }
      return n, err
      }

      // Creates a new netSocket for the next pending connection request.
      func (ns *netSocket) Accept() (*netSocket, error) {
      // syscall.ForkLock doc states lock not needed for blocking accept.
      nfd, _, err := syscall.Accept(ns.fd)
      if err == nil {
      syscall.CloseOnExec(nfd)
      }
      if err != nil {
      return nil, err
      }
      return &netSocket{nfd}, nil
      }

      func (ns *netSocket) Close() error {
      return syscall.Close(ns.fd)
      }

      // Creates a new socket file descriptor, binds it and listens on it.
      func newNetSocket(ip net.IP, port int) (*netSocket, error) {
      // ForkLock docs state that socket syscall requires the lock.
      syscall.ForkLock.Lock()
      // AF_INET = Address Family for IPv4
      // SOCK_STREAM = virtual circuit service
      // 0: the protocol for SOCK_STREAM, there's only 1.
      fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0)
      if err != nil {
      return nil, os.NewSyscallError("socket", err)
      }
      syscall.ForkLock.Unlock()

      // Allow reuse of recently-used addresses.
      if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil {
      syscall.Close(fd)
      return nil, os.NewSyscallError("setsockopt", err)
      }

      // Bind the socket to a port
      sa := &syscall.SockaddrInet4{Port: port}
      copy(sa.Addr[:], ip)
      if err = syscall.Bind(fd, sa); err != nil {
      return nil, os.NewSyscallError("bind", err)
      }

      // Listen for incoming connections.
      if err = syscall.Listen(fd, syscall.SOMAXCONN); err != nil {
      return nil, os.NewSyscallError("listen", err)
      }

      return &netSocket{fd: fd}, nil
      }

      type request struct {
      method string // GET, POST, etc.
      header textproto.MIMEHeader
      body byte
      uri string // The raw URI from the request
      proto string // "HTTP/1.1"
      }

      func parseRequest(c *netSocket) (*request, error) {
      b := bufio.NewReader(*c)
      tp := textproto.NewReader(b)
      req := new(request)

      // First line: parse "GET /index.html HTTP/1.0"
      var s string
      s, _ = tp.ReadLine()
      sp := strings.Split(s, " ")
      req.method, req.uri, req.proto = sp[0], sp[1], sp[2]

      // Parse headers
      mimeHeader, _ := tp.ReadMIMEHeader()
      req.header = mimeHeader

      // Parse body
      if req.method == "GET" || req.method == "HEAD" {
      return req, nil
      }
      if len(req.header["Content-Length"]) == 0 {
      return nil, errors.New("no content length")
      }
      length, err := strconv.Atoi(req.header["Content-Length"][0])
      if err != nil {
      return nil, err
      }
      body := make(byte, length)
      if _, err = io.ReadFull(b, body); err != nil {
      return nil, err
      }
      req.body = body
      return req, nil
      }

      func main() {
      ipFlag := flag.String("ip_addr", "127.0.0.1", "The IP address to use")
      portFlag := flag.Int("port", 8080, "The port to use.")
      flag.Parse()

      ip := net.ParseIP(*ipFlag)
      port := *portFlag
      socket, err := newNetSocket(ip, port)
      defer socket.Close()
      if err != nil {
      panic(err)
      }

      log.Print("===============")
      log.Print("Server Started!")
      log.Print("===============")
      log.Print()
      log.Printf("addr: http://%s:%d", ip, port)

      for {
      // Block until incoming connection
      rw, e := socket.Accept()
      log.Print()
      log.Print()
      log.Printf("Incoming connection")
      if e != nil {
      panic(e)
      }

      // Read request
      log.Print("Reading request")
      req, err := parseRequest(rw)
      log.Print("request: ", req)
      if err != nil {
      panic(err)
      }

      // Write response
      log.Print("Writing response")
      io.WriteString(rw, "HTTP/1.1 200 OKrn"+
      "Content-Type: text/html; charset=utf-8rn"+
      "Content-Length: 20rn"+
      "rn"+
      "<h1>hello world</h1>")
      if err != nil {
      log.Print(err.Error())
      continue
      }
      }
      }








      share







      New contributor




      Joe is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.







      $endgroup$




      I'm new to Go and wanted to implement a web server using system calls to get a better feel for how everything works.



      I'm looking for feedback on idiomatic go especially error handling and using pointers.



      I'm not particularly concerned about the completeness of the code. The primary goal was to learn syscalls in go.



      package main

      // Simple, single-threaded server using system calls instead of the net library.
      //
      // Omitted features from the go net package:
      //
      // - TLS
      // - Most error checking
      // - Only supports bodies that close, no persistent or chunked connections
      // - Redirects
      // - Deadlines and cancellation
      // - Non-blocking sockets

      import (
      "bufio"
      "errors"
      "flag"
      "io"
      "log"
      "net"
      "net/textproto"
      "os"
      "strconv"
      "strings"
      "syscall"
      )

      // netSocket is a file descriptor for a system socket.
      type netSocket struct {
      // System file descriptor.
      fd int
      }

      func (ns netSocket) Read(p byte) (int, error) {
      if len(p) == 0 {
      return 0, nil
      }
      n, err := syscall.Read(ns.fd, p)
      if err != nil {
      n = 0
      }
      return n, err
      }

      func (ns netSocket) Write(p byte) (int, error) {
      n, err := syscall.Write(ns.fd, p)
      if err != nil {
      n = 0
      }
      return n, err
      }

      // Creates a new netSocket for the next pending connection request.
      func (ns *netSocket) Accept() (*netSocket, error) {
      // syscall.ForkLock doc states lock not needed for blocking accept.
      nfd, _, err := syscall.Accept(ns.fd)
      if err == nil {
      syscall.CloseOnExec(nfd)
      }
      if err != nil {
      return nil, err
      }
      return &netSocket{nfd}, nil
      }

      func (ns *netSocket) Close() error {
      return syscall.Close(ns.fd)
      }

      // Creates a new socket file descriptor, binds it and listens on it.
      func newNetSocket(ip net.IP, port int) (*netSocket, error) {
      // ForkLock docs state that socket syscall requires the lock.
      syscall.ForkLock.Lock()
      // AF_INET = Address Family for IPv4
      // SOCK_STREAM = virtual circuit service
      // 0: the protocol for SOCK_STREAM, there's only 1.
      fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0)
      if err != nil {
      return nil, os.NewSyscallError("socket", err)
      }
      syscall.ForkLock.Unlock()

      // Allow reuse of recently-used addresses.
      if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil {
      syscall.Close(fd)
      return nil, os.NewSyscallError("setsockopt", err)
      }

      // Bind the socket to a port
      sa := &syscall.SockaddrInet4{Port: port}
      copy(sa.Addr[:], ip)
      if err = syscall.Bind(fd, sa); err != nil {
      return nil, os.NewSyscallError("bind", err)
      }

      // Listen for incoming connections.
      if err = syscall.Listen(fd, syscall.SOMAXCONN); err != nil {
      return nil, os.NewSyscallError("listen", err)
      }

      return &netSocket{fd: fd}, nil
      }

      type request struct {
      method string // GET, POST, etc.
      header textproto.MIMEHeader
      body byte
      uri string // The raw URI from the request
      proto string // "HTTP/1.1"
      }

      func parseRequest(c *netSocket) (*request, error) {
      b := bufio.NewReader(*c)
      tp := textproto.NewReader(b)
      req := new(request)

      // First line: parse "GET /index.html HTTP/1.0"
      var s string
      s, _ = tp.ReadLine()
      sp := strings.Split(s, " ")
      req.method, req.uri, req.proto = sp[0], sp[1], sp[2]

      // Parse headers
      mimeHeader, _ := tp.ReadMIMEHeader()
      req.header = mimeHeader

      // Parse body
      if req.method == "GET" || req.method == "HEAD" {
      return req, nil
      }
      if len(req.header["Content-Length"]) == 0 {
      return nil, errors.New("no content length")
      }
      length, err := strconv.Atoi(req.header["Content-Length"][0])
      if err != nil {
      return nil, err
      }
      body := make(byte, length)
      if _, err = io.ReadFull(b, body); err != nil {
      return nil, err
      }
      req.body = body
      return req, nil
      }

      func main() {
      ipFlag := flag.String("ip_addr", "127.0.0.1", "The IP address to use")
      portFlag := flag.Int("port", 8080, "The port to use.")
      flag.Parse()

      ip := net.ParseIP(*ipFlag)
      port := *portFlag
      socket, err := newNetSocket(ip, port)
      defer socket.Close()
      if err != nil {
      panic(err)
      }

      log.Print("===============")
      log.Print("Server Started!")
      log.Print("===============")
      log.Print()
      log.Printf("addr: http://%s:%d", ip, port)

      for {
      // Block until incoming connection
      rw, e := socket.Accept()
      log.Print()
      log.Print()
      log.Printf("Incoming connection")
      if e != nil {
      panic(e)
      }

      // Read request
      log.Print("Reading request")
      req, err := parseRequest(rw)
      log.Print("request: ", req)
      if err != nil {
      panic(err)
      }

      // Write response
      log.Print("Writing response")
      io.WriteString(rw, "HTTP/1.1 200 OKrn"+
      "Content-Type: text/html; charset=utf-8rn"+
      "Content-Length: 20rn"+
      "rn"+
      "<h1>hello world</h1>")
      if err != nil {
      log.Print(err.Error())
      continue
      }
      }
      }






      go networking socket server





      share







      New contributor




      Joe is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.










      share







      New contributor




      Joe is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.








      share



      share






      New contributor




      Joe is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 8 mins ago









      JoeJoe

      101




      101




      New contributor




      Joe is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      Joe is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      Joe is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






















          0






          active

          oldest

          votes











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });






          Joe is a new contributor. Be nice, and check out our Code of Conduct.










          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f213643%2fweb-server-using-syscalls-in-go%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          0






          active

          oldest

          votes








          0






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          Joe is a new contributor. Be nice, and check out our Code of Conduct.










          draft saved

          draft discarded


















          Joe is a new contributor. Be nice, and check out our Code of Conduct.













          Joe is a new contributor. Be nice, and check out our Code of Conduct.












          Joe is a new contributor. Be nice, and check out our Code of Conduct.
















          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f213643%2fweb-server-using-syscalls-in-go%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Costa Masnaga

          Fotorealismo

          Sidney Franklin