Skip to content

Commit

Permalink
feat: first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
m9rco committed Oct 11, 2017
1 parent b8676c8 commit f58c51a
Show file tree
Hide file tree
Showing 7 changed files with 365 additions and 0 deletions.
1 change: 1 addition & 0 deletions Chapter1-初识Go语言/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lodings..
1 change: 1 addition & 0 deletions Chapter2-语法概览/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
loding..
127 changes: 127 additions & 0 deletions Chapter3-并发编程综述/Pipe/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/**
* Pipe 管道学习
*
* @author ShaoWei Pu <marco0727@gamil.com>
* @date 2017/10/9
* -------------------------------------------------------------
* 0x01. exec包执行外部命令,它将os.StartProcess进行包装使得它更容易映射到stdin和stdout,并且利用pipe连接i/o.
* 0x02. 命名管道可以被多路复用
*/

package main

import (
"os/exec"
"fmt"
"Go-example/Debug"
"bytes"
"time"
"io"
"os"
)

// output echo
func SimpleEcho() {
cmd := exec.Command("echo", "-n", "I'm Echo")
if err := cmd.Start(); err != nil {
Debug.ErrorMsg(err)
return
}
stdout, err := cmd.StdoutPipe()
if err != nil {
Debug.ErrorMsg(err)
return
}
// 保证关闭输出流
defer stdout.Close()
output := make([]byte, 30)
n, err := stdout.Read(output)
if err != nil {
Debug.ErrorMsg(err)
return
}
fmt.Printf("%s\n", output[:n])
}

// output pipe
func anonymousPipe() {
cmdLeft := exec.Command("ps", "aux")
cmdRight := exec.Command("grep", "php")
var outputBuf bytes.Buffer
cmdLeft.Stdout = &outputBuf // stdout
if err := cmdLeft.Start(); err != nil {
Debug.ErrorMsg(err)
return
}
if err := cmdLeft.Wait(); err != nil {
Debug.ErrorMsg(err)
return
}
cmdRight.Stdin = &outputBuf // stdin
var outputBufRight bytes.Buffer
cmdRight.Stdout = &outputBufRight
if err := cmdRight.Start(); err != nil {
Debug.ErrorMsg(err)
return
}
if err := cmdRight.Wait(); err != nil {
Debug.ErrorMsg(err)
return
}
fmt.Printf("%s \n", outputBufRight.Bytes())
}

// 原子操作
func fileBasedPipe() {
reader, writer, err := os.Pipe()
if err != nil {
fmt.Printf("Error: Couldn't create the named pipe: %s\n", err)
}
go func() {
output := make([]byte, 100)
n, err := reader.Read(output)
if err != nil {
fmt.Printf("Error: Couldn't read data from the named pipe: %s\n", err)
}
fmt.Printf("Read %d byte(s). [file-based pipe]\n", n)
}()
input := make([]byte, 26)
for i := 0; i < 26; i++ {
input[i] = byte(i)
}
n, err := writer.Write(input)
if err != nil {
fmt.Printf("Error: Couldn't write data to the named pipe: %s\n", err)
}
fmt.Printf("Written %d byte(s). [file-based pipe]\n", n)
time.Sleep(200 * time.Millisecond)
}

func inMemorySyncPipe() {
reader, writer := io.Pipe()
go func() {
output := make([]byte, 100)
n, err := reader.Read(output)
if err != nil {
fmt.Printf("Error: Couldn't read data from the named pipe: %s\n", err)
}
fmt.Printf("Read %d byte(s). [in-memory pipe]\n", n)
}()
input := make([]byte, 26)
for i := 65; i <= 90; i++ {
input[i-65] = byte(i)
}
n, err := writer.Write(input)
if err != nil {
fmt.Printf("Error: Couldn't write data to the named pipe: %s\n", err)
}
fmt.Printf("Written %d byte(s). [in-memory pipe]\n", n)
time.Sleep(200 * time.Millisecond)
}

func main() {
// SimpleEcho() // 通过调用Linux命令输出Echo // Ps: 妈的 第一个Demo 就不是想象中的样子 exec: StdoutPipe after process started
// anonymousPipe() // ps aux | grep php << 这个好使
fileBasedPipe()
inMemorySyncPipe()
}
205 changes: 205 additions & 0 deletions Chapter3-并发编程综述/Signal/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
/**
* Signal 信号
*
* @author ShaoWei Pu <marco0727@gamil.com>
* @date 2017/10/9
* -------------------------------------------------------------
* 0x01. `kill -l`
* - 标准信号: 1 - 31
* - 实时信号:34 - 63
* 0x02. 这章看起来太枯燥,等后面弄完在来温习
*/
package main

import (
"bytes"
"errors"
"fmt"
"io"
"os"
"os/exec"
"os/signal"
"runtime/debug"
"strconv"
"strings"
"sync"
"syscall"
"time"
)

func main() {
//simpleSignal()
go func() {
time.Sleep(5 * time.Second)
sendSignal()
}()
handleSignal()
}

// 创建一个等待信号的进程
func simpleSignal() {
sigRecv := make(chan os.Signal, 1)
sigs := []os.Signal{syscall.SIGINT, syscall.SIGQUIT,syscall.SIGTERM}
signal.Notify(sigRecv, sigs...)
for sig := range sigRecv {
fmt.Printf("Received a signal:%s\n", sig)
}
}

func handleSignal() {
sigRecv1 := make(chan os.Signal, 1)
sigs1 := []os.Signal{syscall.SIGINT, syscall.SIGQUIT}
fmt.Printf("Set notification for %s... [sigRecv1]\n", sigs1)
signal.Notify(sigRecv1, sigs1...)
sigRecv2 := make(chan os.Signal, 1)
sigs2 := []os.Signal{syscall.SIGQUIT}
fmt.Printf("Set notification for %s... [sigRecv2]\n", sigs2)
signal.Notify(sigRecv2, sigs2...)

var wg sync.WaitGroup
wg.Add(2)
go func() {
for sig := range sigRecv1 {
fmt.Printf("Received a signal from sigRecv1: %s\n", sig)
}
fmt.Printf("End. [sigRecv1]\n")
wg.Done()
}()
go func() {
for sig := range sigRecv2 {
fmt.Printf("Received a signal from sigRecv2: %s\n", sig)
}
fmt.Printf("End. [sigRecv2]\n")
wg.Done()
}()

fmt.Println("Wait for 2 seconds... ")
time.Sleep(2 * time.Second)
fmt.Printf("Stop notification...")
signal.Stop(sigRecv1) // 取消之前调用 signal.Notify 函数时告知signal处理程序需要自行处理若干信号的行为,
close(sigRecv1) // 只有把当初传递给signal.Notify函数的那个signal 接受通道作为调用signal.stop函数时的参数值,才能取消行为
fmt.Printf("done. [sigRecv1]\n")
wg.Wait()
}

func sendSignal() {
defer func() {
if err := recover(); err != nil {
fmt.Printf("Fatal Error: %s\n", err)
debug.PrintStack()
}
}()
// ps aux | grep "signal" | grep -v "grep" | grep -v "go run" | awk '{print $2}'
cmds := []*exec.Cmd{
exec.Command("ps", "aux"),
exec.Command("grep", "signal"),
exec.Command("grep", "-v", "grep"),
exec.Command("grep", "-v", "go run"),
exec.Command("awk", "{print $2}"),
}
output, err := runCmds(cmds)
if err != nil {
fmt.Printf("Command Execution Error: %s\n", err)
return
}
pids, err := getPids(output)
if err != nil {
fmt.Printf("PID Parsing Error: %s\n", err)
return
}
fmt.Printf("Target PID(s):\n%v\n", pids)
for _, pid := range pids {
proc, err := os.FindProcess(pid)
if err != nil {
fmt.Printf("Process Finding Error: %s\n", err)
return
}
sig := syscall.SIGQUIT
fmt.Printf("Send signal '%s' to the process (pid=%d)...\n", sig, pid)
err = proc.Signal(sig)
if err != nil {
fmt.Printf("Signal Sending Error: %s\n", err)
return
}
}
}

func getPids(strs []string) ([]int, error) {
var pids []int
for _, str := range strs {
pid, err := strconv.Atoi(strings.TrimSpace(str))
if err != nil {
return nil, err
}
pids = append(pids, pid)
}
return pids, nil
}

func runCmds(cmds []*exec.Cmd) ([]string, error) {
if cmds == nil || len(cmds) == 0 {
return nil, errors.New("The cmd slice is invalid!")
}
first := true
var output []byte
var err error
for _, cmd := range cmds {
fmt.Printf("Run command: %v\n", getCmdPlaintext(cmd))
if !first {
var stdinBuf bytes.Buffer
stdinBuf.Write(output)
cmd.Stdin = &stdinBuf
}
var stdoutBuf bytes.Buffer
cmd.Stdout = &stdoutBuf
if err = cmd.Start(); err != nil {
return nil, getError(err, cmd)
}
if err = cmd.Wait(); err != nil {
return nil, getError(err, cmd)
}
output = stdoutBuf.Bytes()
//fmt.Printf("Output:\n%s\n", string(output))
if first {
first = false
}
}
var lines []string
var outputBuf bytes.Buffer
outputBuf.Write(output)
for {
line, err := outputBuf.ReadBytes('\n')
if err != nil {
if err == io.EOF {
break
} else {
return nil, getError(err, nil)
}
}
lines = append(lines, string(line))
}
return lines, nil
}

func getCmdPlaintext(cmd *exec.Cmd) string {
var buf bytes.Buffer
buf.WriteString(cmd.Path)
for _, arg := range cmd.Args[1:] {
buf.WriteRune(' ')
buf.WriteString(arg)
}
return buf.String()
}

func getError(err error, cmd *exec.Cmd, extraInfo ...string) error {
var errMsg string
if cmd != nil {
errMsg = fmt.Sprintf("%s [%s %v]", err, (*cmd).Path, (*cmd).Args)
} else {
errMsg = fmt.Sprintf("%s", err)
}
if len(extraInfo) > 0 {
errMsg = fmt.Sprintf("%s (%v)", errMsg, extraInfo)
}
return errors.New(errMsg)
}
14 changes: 14 additions & 0 deletions Chapter3-并发编程综述/Socket/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Socket 来啦!!!
*
* @author ShaoWei Pu <marco0727@gamil.com>
* @date 2017/10/10
* -------------------------------------------------------------
* 0x01. 深入理解TPC/IP [晚上回去一定要看要看要看要看看看...]
* 0x02.
*/
package main

func main() {

}
Empty file added Debug/README.md
Empty file.
17 changes: 17 additions & 0 deletions Debug/Tools.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package Debug

import (
"runtime"
"fmt"
)

/**
返回调用位置信息
*/
func ErrorMsg(entity error) {
if pc, file, line, ok := runtime.Caller(1); ok != false {
f := runtime.FuncForPC(pc)
fmt.Printf(" [调用方法] %s \n [调用位置] %s %v \n [ErrorMsg] %s\n", f.Name(), file, line, entity)
}
return
}

0 comments on commit f58c51a

Please sign in to comment.