Go实现简单的Socket服务端笔记(三)

利用goroutine实现同时多个客户端连接

将数据读取放入单独的方法中,利用goroutine运行

本文代码查看github:
https://github.com/zboyco/go-server/tree/step-3

要实现多个客户端连接,需要将每个客户端放入单独的线程处理,通常我们使用多线程实现这个功能,但Go语言提供的 goroutine, 可以非常方便的实现并行(goroutine并不是多线程)

  1. 将接收数据的相关代码放入单独的方法中:

Go学习杂记

  1. 方法
    方法实际上也是函数,只是在声明时,关键字func喝方法名之间增加了一个参数(接收者)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    type user struct {
    name string
    email string
    }
    func (u user) notify() {
    fmt.Printf("Sending User Email To %s<%s>\n",u.name,u.email)
    }
    func (u *user) changeEmail(email string) {
    u.email = email
    }
  2. defer 关键字
    在函数或方法中,用defer标识的语句将会在函数或方法返回后执行
    1
    2
    3
    4
    5
    6
    7
    8
    9
    func (p *Pool) Release(r io.Closer) {
    p.m.Lock()
    defer p.m.Unlock()

    if p.closed {
    r.Close()
    return
    }
    }
  3. chan 通道
    1
    2
    3
    4
    5
    6
    7
    type Test struct {
    // 普通通道.
    complete chan error

    // 单项通道,只能读取.
    timeout <-chan time.Time
    }
  4. select 语句
    select 中没有default分支,程序将会阻塞等待
    1
    2
    3
    4
    5
    6
    7
    select {
    case err := <-r.complete:
    return err

    case <-r.timeout:
    return ErrTimeout
    }
    select 中有default分支,程序将会将阻塞转变为非阻塞,如果通道有内容则接收,没有则执行default分支
    1
    2
    3
    4
    5
    6
    7
    8
    select {
    case <-r.interrupt:
    signal.Stop(r.interrupt)
    return true

    default:
    return false
    }

Reach Router

今天在看一个项目的时候,无意间看到推荐 reach/router 这个React路由组件,然后就看了下组件的使用,感觉使用比react-router更加简单直接,库也比较小,用法和react-router类似但是更简洁,这里记录下换成reach时碰到的问题,官网地址如下:

Reach Router

  1. router 会自动跳转到 主路由加载的内容上
    其实就是focus变化,reach会将focus指定到主router渲染的内容,所以就导致页面会”跳”到新内容上,解决办法是给所有router添加 primary={false} 属性:
    1
    2
    3
    4
    <Router primary={false}>
    <Company path="/" />
    <Brand path="/Brand" />
    </Router>
  2. 嵌套路由(router加载的组件里再使用router)
    在子组件里使用路由时也使用router包围即可:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    render(
    <Router>
    <Home path="/" />
    <Dash path="dashboard/*" />
    </Router>
    )

    const Dash = () => (
    <div>
    <p>A nested router</p>
    <Router>
    <DashboardGraphs path="/" />
    <InvoiceList path="invoices" />
    </Router>
    </div>
    )
  3. NavLink
    reach 没有 react-router 里的 NavLink,不能直接通过activeClassName的方式增加属性,但reach的Link组件提供了getProps参数,可以通过该方法实现NavLink:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    import React, { Component } from 'react';
    import { Link } from '@reach/router';

    export default class NavLink extends Component {
    render() {
    return (
    <React.Fragment>
    <Link
    {...this.props}
    getProps={({ isCurrent, isPartiallyCurrent, href, location }) => {
    // the object returned here is passed to the
    // anchor element's props
    if (href !== "/") {
    return isPartiallyCurrent ? { className: 'active' } : null;
    } else {
    return isCurrent ? { className: 'active' } : null;
    }
    }}
    />
    </React.Fragment>
    )
    }
    }
    其中四个参数意义:
  • isCurrent - true if the location.pathname is exactly the same as the anchor’s href.
  • isPartiallyCurrent - true if the location.pathname starts with the anchor’s href.
  • href - the fully resolved href of the link.
  • location - the app’s location.

React 配置 SASS

学习react时,在项目中使用sass编辑样式,记录配置方法:

#安装

1
npm install sass-loader node-sass --save-dev

#配置
打开react的webpack配置,找到module下的rules,然后找到最后一个配置,修改成如下的样子

1
2
3
4
5
6
7
8
9
10
11
12
{

exclude: [/\.js$/,/\.html$/,/\.json$/,/\.scss$/],
loader: require.resolve('file-loader'),
options: {
name: 'static/media/[name].[hash:8].[ext]',
},
},
{
test:/\.scss$/,
loaders:['style-loader','css-loader','sass-loader']
}

注意,我们只是修改了 webpack.config.dev.js, 如果要在生产环境中生效,需要在webpack.config.prod.js做同样的配置。

React 引用 jQuery

原由

计划用 React 做一个前台展示网站,设计用到了jQuery Smoove这个插件,所以在网上找了下怎么在 React 中引入jQuery,并让插件可以正常使用.

安装 jQuery

npm install jquery

注意,全是小写字母,不能写成 jQuery,会安装成功,但无法编译通过。

使用

  1. 直接使用
    如果直接使用 jQuery 而不使用其他基于 jq 的插件的话,那么直接在 react 文件里 import 即可:
    import $ from 'jquery';
  2. 为插件服务
    如果有其他基于 jq 的插件,则需要在 webpack 中添加全局设置(我使用的 create-react-app 初始化的项目).
    找到webpack配置路径:
    node_modules/react-scripts/config/webpack.config.dev.js(webpack.config.prod.js)
    在 plugins 属性中添加以下代码即可:
    1
    2
    3
    4
    5
    new webpack.ProvidePlugin({
    $:"jquery",
    jQuery:"jquery",
    "window.jQuery":"jquery"
    }),

大功告成!

create-react-app 初始化的项目在node_modules,直接修改的话重新安装包就被覆盖了,如果有需要的话,可以执行 yarn eject,把引用的包本地化后再修改,或者使用其他脚手架初始化项目也可。